<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://fare9.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://fare9.github.io/" rel="alternate" type="text/html" /><updated>2025-06-11T04:27:39+00:00</updated><id>https://fare9.github.io/feed.xml</id><title type="html">Eduardo Blázquez’s Personal Webpage</title><subtitle>Nothing to write here...</subtitle><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><entry><title type="html">Writing an IR from Scratch and survive to write a post</title><link href="https://fare9.github.io/compilers/programming/writing-an-ir-from-scratch/" rel="alternate" type="text/html" title="Writing an IR from Scratch and survive to write a post" /><published>2024-06-21T00:00:00+00:00</published><updated>2024-06-22T01:35:00+00:00</updated><id>https://fare9.github.io/compilers/programming/writing-an-ir-from-scratch</id><content type="html" xml:base="https://fare9.github.io/compilers/programming/writing-an-ir-from-scratch/"><![CDATA[<p>In this post, I will talk about the first version of the Intermediate Representation I designed for <em>Kunai Static Analyzer</em>, this is a dalvik analysis library that I wrote as a project for my PhD, also as a way of learning about the Dalvik file format and improving my programming skills.</p>

<h2 id="authors">Authors</h2>

<p>Writer:</p>

<ul>
  <li>Eduardo Blazquez</li>
</ul>

<p>Technical and English reviewer:</p>

<ul>
  <li><a href="https://twitter.com/yates82">Robert Yates</a></li>
</ul>

<h2 id="kunai-static-analyzer">Kunai Static Analyzer</h2>

<p>Kunai was a static analysis library for dalvik bytecode. This library was published on Github, and it also was a paper published in the journal <em>SoftwareX</em> describing the projects and its benefits against another tool of the state of the art.</p>

<p>You can find the source code here: https://github.com/Fare9/KUNAI-static-analyzer</p>

<p>And the paper here: https://www.sciencedirect.com/science/article/pii/S2352711023000663</p>

<p>Although the project is discontinued (a new version is being written here <a href="https://github.com/Fare9/Shuriken-Analyzer/">Shuriken</a>), I thought it would be interesting to write about my experience of how I wrote the first version of its Intermediate Representation (from now on IR), how I implemented the different algorithms, and how I transformed Dalvik bytecode into this IR.</p>

<p>As I said, this IR is the first version I wrote for Kunai, after that I decided to move my implementation to <a href="https://mlir.llvm.org/">MLIR</a>, an approach for writing specific IRs using a reusable and extensible compiler infrastructure. You can find my presentation of this new IR that I implemented, at <a href="https://www.youtube.com/watch?v=hfqOivYdD40">EuroLLVM2023</a>.</p>

<p>As I said, in this post I will dig into the process of creating an IR for supporting analysis of Dalvik Bytecode, the algorithms I followed and implemented, and finally the process for lifting the dalvik bytecode into this IR.</p>

<p>Please, grab a drink, play your favorite music (I recommend the following one if you want to chill: <a href="https://www.youtube.com/watch?v=Lk3LesfKg2c">Dreamcatcher chill</a>, or the next one if you prefer something with more rhythm: <a href="https://www.youtube.com/watch?v=a4KPtXOYlME">Dreamcatcher no ballad</a>).</p>

<h2 id="references">References</h2>

<p>For the design and development of the IR I read chapters from different books, and I studied the code from different projects. Here you can find those books and projects:</p>

<h3 id="books">Books</h3>

<ul>
  <li>Advanced Compiler Design &amp; Implementation</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/acdi.jpg">
        <img src="/assets/images/kunai_ir/acdi.jpg" />
    </a>
</figure>

<ul>
  <li>An Introduction to the Theory of Optimizing Compilers</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/aitoc.jpg">
        <img src="/assets/images/kunai_ir/aitoc.jpg" />
    </a>
</figure>

<ul>
  <li>Compilers Principle, Techniques &amp; Tools</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/dragon-2007.jpg">
        <img src="/assets/images/kunai_ir/dragon-2007.jpg" />
    </a>
</figure>

<ul>
  <li>Introduction to Compilers and Language Design</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/icld.jpg">
        <img src="/assets/images/kunai_ir/icld.jpg" />
    </a>
</figure>

<ul>
  <li>SSA-based Compiler Design</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/ssa-based_compiler_design.jpg">
        <img src="/assets/images/kunai_ir/ssa-based_compiler_design.jpg" />
    </a>
</figure>

<h3 id="projects">Projects</h3>

<ul>
  <li><a href="https://github.com/llvm/llvm-project">LLVM</a></li>
  <li><a href="https://github.com/JonathanSalwan/Triton">Triton</a></li>
  <li><a href="https://github.com/cea-sec/miasm">Miasm</a></li>
  <li><a href="https://github.com/plum-umd/redexer">Redexer</a></li>
  <li><a href="https://github.com/soot-oss/soot">Soot</a></li>
  <li><a href="https://www.abartel.net/dexpler/">Dexpler</a></li>
  <li><a href="https://spinsel.dev/assets/2020-06-17-ghidra-brainfuck-processor-1/ghidra_docs/language_spec/html/pcoderef.html">P-Code (An IR used in Ghidra)</a></li>
  <li><a href="https://docs.binary.ninja/dev/bnil-overview.html">Binary Ninja IL</a></li>
  <li><a href="https://binary.ninja/presentations/Modern%20Binary%20Analysis%20with%20ILs%20with%20notes.pdf">Modern Binary Analysis with ILs</a></li>
  <li><a href="https://docs.angr.io/en/latest/advanced-topics/ir.html">Angr VEX IR</a></li>
  <li><a href="https://book.rada.re/disassembling/esil.html">Radare2 ESIL</a></li>
</ul>

<h2 id="mjolnir---kunais-ir">MjolnIR - Kunai’s IR</h2>

<p>My idea behind writing an IR for Kunai came from all the work I did during my PhD using Androguard. Many times using Androguard, I had to rely on the output of its disassembler and manually check the opcodes or even the mnemonic from the operation. While this process was easy for small analyses, it became hard for other projects. For example, I remember helping my friend Julien with one of his papers, at that moment we wanted to write a static taint analysis tool for Dalvik, and one of the ideas we had was to include a simple IR that would help us to recognize instructions in Androguard. It was at that moment when I saw the disadvantages of using Androguard, there was not a representation that could help us with the analysis (some time after that I discovered an Abstract Syntax Tree representation, but it is mostly used for the decompiler). After that, once I was writing Kunai, I thought that Kunai would benefit from an IR that would help analysts to write analyses with Kunai.</p>

<p>First of all, the most challenging decision choice was “what’s a cool name I can give it?”. Of course, a cool project needs a cool name. And because the project already had the name <em>Kunai</em> (a japanese farming tool popular for being the most used weapon in the manga/anime Naruto), the name of a weapon would be really cool as a name, and at that moment I remembered the following:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/mjolnir-thor.jpg">
        <img src="/assets/images/kunai_ir/mjolnir-thor.jpg" />
    </a>
</figure>

<p><strong>Mjölnir</strong>, the weapon of <strong>Thor</strong>, god of thunder in Norse Mythology. I had a cool name, and if I wrote it like <em>MjolnIR</em>, I could say that the last two characters come from <em>Intermediate Representation</em>.</p>

<p>Although the idea was good, my knowledge of the IRs was limited, and mostly based on using tools like <a href="https://github.com/JonathanSalwan/Triton">Triton</a> that gave me access to <a href="https://github.com/llvm/llvm-project">LLVM-IR</a> code, or analyzing binaries using <a href="https://ghidra-sre.org/">Ghidra</a> and observing the generated P-code. Of course, I also remembered the little knowledge I gained in the Compiler’s class during the undergraduate bachelor in Computer Engineering. But I was willing to write the IR, and I had enough bibliography to start reading, as well as different projects to start learning from their code.</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/speed-reading.gif">
        <img src="/assets/images/kunai_ir/speed-reading.gif" />
    </a>
</figure>

<h3 id="mjolnir---structure-of-an-ir">MjolnIR - Structure of an IR</h3>

<p>Each Intermediate Representation or Intermediate Language can have its own shape, and own design. We can have that it is text-based or binary-based, or even a mix of both (for allowing modifications directly with a text-editor but fast processing with tools). We can have the next like Intermediate Representations (from the book Introduction to Compilers and Language Design) :</p>

<ul>
  <li>Abstract Syntax Tree (AST): although this representation is commonly used by the compiler’s front-end, it can be also used as an IR. Small simplifications are allowed in this representation. We can find that Triton uses a tree to represent the different expressions executed by its symbolic execution engine, and it is used for different translations like: expression tree to Z3 for expressions solving, or expression tree to LLVM IR. Being honest, in my first design I included some structures in the IR to allow a tree design, but I wasn’t completely sure about it, so I removed it from the design.</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/ast.png">
        <img src="/assets/images/kunai_ir/ast.png" />
    </a>
    <figcaption style="text-align: center;">An Abstract Syntax Tree for a source code</figcaption>
</figure>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/triton_expression_tree.svg">
        <img src="/assets/images/kunai_ir/triton_expression_tree.svg" style="background-color: white; padding: 10px;" />
    </a>
    <figcaption style="text-align: center;">A tree used by Triton to represent an expression</figcaption>
</figure>

<ul>
  <li>Directed Acyclic Graph (DAG): this is one step simplified from the AST, in a compiler this DAG can provide us with the type and value of each node, but in binary analysis, this information should be recovered. Probably it could be more useful for a compiler than for a binary analysis tool, since the information that would be needed to be recovered for using it would require a big effort.</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/dag.jpg">
        <img src="/assets/images/kunai_ir/dag.jpg" />
    </a>
    <figcaption style="text-align: center;">A simple dag</figcaption>
</figure>

<ul>
  <li>Control-Flow Graph (CFG): this is a commonly used representation in binary analysis. A CFG is a graph in which blocks and edges represent the code and the control-flow of a function, in source code we can have that each block represents one statement from the source code, but in binary analysis commonly a block is a list of instructions (assembly or another intermediate language) with one entry point, and one exit point (a termination instruction, or an instruction to transfer the control of execution)</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/cfg-code.svg">
        <img src="/assets/images/kunai_ir/cfg-code.svg" />
    </a>
    <figcaption style="text-align: center;">A Control-Flow Graph from a source code</figcaption>
</figure>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/cfg-binary.png">
        <img src="/assets/images/kunai_ir/cfg-binary.png" />
    </a>
    <figcaption style="text-align: center;">A Control-Flow Graph from a binary</figcaption>
</figure>

<ul>
  <li>Static-Single Assignment (SSA): this representation form represents an intermediate language with one restriction, the variables can be assigned only once, so their value cannot change. In case we want to give a new value to a previously defined variable, we create a new variable but with another subindex. This makes algorithms like <em>def-use</em> trivial (we’ll see later in a part dedicated to the implemented algorithms). In some cases, we will need a special instruction called <em>phi</em> to create a new value that will hold a value depending on where the control-flow came from.</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/SSA_example.png">
        <img src="/assets/images/kunai_ir/SSA_example.png" />
    </a>
    <figcaption style="text-align: center;">An Example of SSA IR</figcaption>
</figure>

<ul>
  <li>Linear IR: an intermediate representation that represents the instructions one after another as a sequence, which is similar to the assembly language. We have instructions to transfer values between memory and multiple registers etc. An example could be Dalvik’s bytecode, which is based on registers, and it is a kind of linear IR.</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/dalvik-bytecode.png">
        <img src="/assets/images/kunai_ir/dalvik-bytecode.png" />
    </a>
    <figcaption style="text-align: center;">An Example of Dalvik Bytecode</figcaption>
</figure>

<ul>
  <li>Stack-Machine IR: In this case, we have a stack that is used to “store” values from the program, this kind of IR is designed to execute on a virtual stack machine. A good example of this one would be the bytecode of Java, which is stack-based.</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/java-bytecode.webp">
        <img src="/assets/images/kunai_ir/java-bytecode.webp" />
    </a>
    <figcaption style="text-align: center;">An example of Java bytecode</figcaption>
</figure>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/stack-vs-register.png">
        <img src="/assets/images/kunai_ir/stack-vs-register.png" />
    </a>
    <figcaption style="text-align: center;">A comparison between a stack and register bytecode</figcaption>
</figure>

<p>In general, my observation from the different books and projects is that an IR has a container for storing functions/methods from the programs. As I said, many of the IRs I have used so far use a <em>Control-Flow Graph</em> representation, so inside this container we have a block structure, and inside of the blocks a list of instructions.</p>

<p>The blocks in the CFG will have a single point of entry, and a single point of exit. The point of exit can be an instruction that represents a jump, a conditional jump or a switch statement. We can also find some instructions that have only a fallthrough (another instruction that doesn’t jump). Or in another case, we can find an exit block that ends with a return or throwing an exception.</p>

<p>Finally, we have the instructions inside the blocks. These instructions can represent a subset of real assembly instructions, and they can be used to represent all the semantics from a real machine. Of course, the complexity of these IR instructions will depend on the machines we want to represent. Mostly, we should have the following category of instructions:</p>

<ul>
  <li>Control-Flow instructions: instructions representing jumps, returns, switch, etc.</li>
  <li>Data-Flow instructions: instructions to access memory for reading or writing to memory.</li>
  <li>Operations: it wouldn’t be useful having access to memory data if we cannot work with that data, so here we have this category. The category would include binary operations, unary operations, comparisons, and assignments.</li>
  <li>Values: we need some type of data to work with. Memory can have different representations, for example, a map of addresses. We can have registers, these registers can represent those from the machine, or we could have virtual registers. In an SSA representation, we have an infinite number of registers, and each register can be assigned a value only once. Register and memory can have an associated type, or at least an associated size.</li>
</ul>

<p>In the next section, we will cover all these different instructions from the point of view of MjolnIR, and what are the instructions that I decided to implement with a schematic view of the instructions. Later I will present the implementation in C++ code of the types and some of the design decisions.</p>

<h3 id="mjolnir---structure-of-mjolnir">MjolnIR - Structure of MjolnIR</h3>

<p>Although I had many examples, deciding how to create one IR is not something very straightforward or easy, so my best resource in this case was reading about <a href="https://docs.binary.ninja/dev/bnil-overview.html">Binary Ninja ILs</a>, and also the book <em>Advanced Compiler Design &amp; Implementation</em>, in both resources they talk about three-levels of representation, from a more low level syntax like assembly to higher level closer to source code (llil-mlil-hlil), and I thought that the <em>Medium Level IL</em> was a good design for what I wanted to do.</p>

<p>First of all, I thought I would need to represent a Method from Dalvik, and the best way to represent a method was using a control-flow graph, and this control-flow graph would have blocks.</p>

<p>Secondly, the blocks would have instructions, but we have different types of instructions, so let’s call all of them <em>statements</em>, and here we have condition-flow instructions, a nop instruction, and return instructions. But a fundamental one was the <em>expressions</em>, these expressions are the instructions that perform operations, we have assignments, we have arithmetic-logic instructions, comparisons, call to instructions, and memory usage. These expressions are applied over registers which have a type, so we also have types representing different things like registers, memory, constant ints, called methods, classes and even temporal registers.</p>

<p>I joined all of these, and I ended up having a type of tree structure, I represented that structure using a (probably not really well) Backus-Naur form (<a href="https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form">BNF</a>). In the next section, I will show the BNFs that represent all the statements from the IR, I will also talk about the different instructions that are part of that BNF and what I represent with them.</p>

<h4 id="backus-naur-forms">Backus-Naur forms</h4>

<h5 id="irstmnt"><strong>IRStmnt</strong></h5>

<p>At the top of the IR we have the statements, these will be every instruction from the IR that could be executed by the program, between these IRStmnt are the expressions (explained later), but more specific statements are those that change the Control-Flow Graph from the function/method, these are conditional and unconditional jumps, return statements, etc.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>IRStmnt     --&gt;     IRUJmp   |
                    IRCJmp   |
                    IRRet    |
                    IRBlock  |
                    IRNop    |
                    IRSwitch |
                    IRExpr 

IRUJmp      --&gt;     jmp addr
IRCJmp      --&gt;     if (IRStmnt) { jmp addr } NEXT fallthrough_addr
IRRet       --&gt;     Ret IRStmnt
IRBlock     --&gt;     IRStmnt1, IRStmnt2, ..., IRStmntN
IRSwitch    --&gt;     switch (IRStmnt) { case X1 -&gt; addr, case X2 -&gt; addr, case XN -&gt; addr }
</code></pre></div></div>

<p>All the instructions that are in a block are statements. Even the Blocks are statements. As I previously said, an IR needs Control-Flow instructions, these kinds of instructions would be:</p>

<ul>
  <li>Unconditional jumps that specify the address where they jump.</li>
  <li>Conditional jumps that takes a comparison a statement and the address where to jump to in the case where the condition is met.</li>
  <li>Return instruction that can specify a returned value.</li>
  <li>Blocks, in my design blocks are statements too, and they contain a list of instructions.</li>
  <li>Switch, like conditional jumps but these take an expression for the value to check and lookup various cases of addresses where to jump to.</li>
  <li>Expressions, expressions are a special type of statements that will be subdivided into other instructions, we will see it in the next section.</li>
</ul>

<h5 id="irexpr"><strong>IRExpr</strong></h5>

<p>The IR requires to support various instructions from the code, these are what we call IRExpr, these kinds of instructions don’t modify the control flow of the method but apply different kinds of operations to the variables/registers/memory in the program. They can affect the call-graph of a program, since one of the expressions allows calling other methods.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>IRExpr    --&gt;   IRBinOp   |
                IRUnaryOp | 
                IRAssign  |
                IRPhi     |
                IRCall    |
                IRLoad    |
                IRStore   |
                IRZComp   |
                IRBComp   |
                IRNew     |
                IRAlloca  |
                IRType    
                
IRBinOp   --&gt;   IRExpr &lt;- IRExpr bin_op_t IRExpr
IRUnaryOp --&gt;   IRExpr &lt;- unary_op_t IRExpr
IRAssign  --&gt;   IRExpr &lt;- IRExpr
IRPhi     --&gt;   IRExpr &lt;- IRExpr, IRExpr, ..., IRExpr
IRCall    --&gt;   IRExpr(IRExpr1, IRExpr2, ..., IRExprN)
IRLoad    --&gt;   IRExpr &lt;- *IRExpr
IRStore   --&gt;   *IRExpr &lt;- IRExpr
IRZComp   --&gt;   IRExpr zero_comp_t
IRBComp   --&gt;   IRExpr comp_t IRExpr
IRNew     --&gt;   IRExpr &lt;- new IRExpr
IRAlloca  --&gt;   IRExpr &lt;- new IRExpr[IRExpr]

# kind of operations
bin_op_t  --&gt;   ADD_OP_T   |
                SUB_OP_T   |
                S_MUL_OP_T |
                U_MUL_OP_T |
                S_DIV_OP_T |
                U_DIV_OP_T |
                MOD_OP_T
unary_op_t   --&gt;   INC_OP_T    |
                   DEC_OP_T    |
                   NOT_OP_T    |
                   NEG_OP_T    |
                   CAST_OP_T   |
                   Z_EXT_OP_T  |
                   S_EXT_OP_T
zero_comp_t  --&gt;   EQUAL_ZERO_T |
                   NOT_EQUAL_ZERO_T
comp_t       --&gt;   EQUAL_T              |
                   NOT_EQUAL_T          |
                   GREATER_T            |
                   GREATER_EQUAL_T      |
                   LOWER_T              |
                   ABOVE_T              |
                   ABOVE_EQUAL_T        |
                   BELOW_T
</code></pre></div></div>

<p>Here we have the second type of instructions, we have operations that work with data, loading and storing data in memory, assigning values to registers, doing comparisons and memory allocations, etc.</p>

<ul>
  <li>Binary operations: those expressions that have two operands and store the result in a register/temporal register. We have different binary operations: add operation, sub operation, signed and unsigned multiplication and division, and finally mod operation.</li>
  <li>Unary operations: expressions that only use one operand, the result is stored in a register/temporal register. We have different unary operations: increment, decrement, not, neg, casting to a different type, zero extension and sign extension.</li>
  <li>Assignment operation: assign a value from one register/temporal register to another.</li>
  <li>PHI instruction: this instruction is used in IRs to represent the same value coming from different blocks. The Phi instruction has as many operands as predecessor blocks. Conceptually, Phi returns a value depending on which block is executed before the phi instruction.</li>
</ul>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/phi-instruction.png">
        <img src="/assets/images/kunai_ir/phi-instruction.png" />
    </a>
    <figcaption style="text-align: center;">Example of a PHI instruction.</figcaption>
</figure>

<ul>
  <li>Call instruction: this instruction has a Callee that is called, it gets a variable number of operands, and it optionally returns a value.</li>
  <li>Load and Store operations: used to load and store values from memory. In the case of Android, here we would have access to the class fields.</li>
  <li>Zero comparison operation: a comparison with a zero value, to know if the provided expression is equals or not equal to zero. The value returned by the operation is commonly used in a conditional jump.</li>
  <li>Binary comparison operation: this operation receives two expressions and a type of comparison, the available comparisons are equal, not equal, greater, greater-equal, lower, above, above-equal and below (for signed and unsigned comparisons). The value returned by the operation is commonly used in a conditional jump.</li>
  <li>New operation: used to initialize a new object.</li>
  <li>Alloca operation: used to initialize arrays with a specific size.</li>
  <li>Type: this is an especial expression that represents the different types available for the IR.</li>
</ul>

<h5 id="irtype"><strong>IRType</strong></h5>

<p>For supporting the types we find in the binary code, we have written a series of classes which derive from a superclass named IRType, as derived classes we have: registers, constant values, strings, memory, callee types.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>IRType   --&gt;   IRReg |
               IRTempReg |
               IRConstInt |
               IRMemory |
               IRString |
               IRCallee |
               IRField  |
               IRClass  |
               IRFundamental |
               NONE

IRFundamental   --&gt; F_BOOLEAN   |
                    F_BYTE      |
                    F_CHAR      |
                    F_DOUBLE    |
                    F_FLOAT     |
                    F_INT       |
                    F_LONG      |
                    F_SHORT     |
                    F_VOID
</code></pre></div></div>

<p>Finally, we have values that are used in the expressions and also in the statements. Some IRs call some of these <code class="language-plaintext highlighter-rouge">Values</code>, others have <code class="language-plaintext highlighter-rouge">registers</code>, etc. In case of MjolnIR, I included registers that represent the registers from Dalvik, and also temporal registers that are used as results for some of the expression operations. Now we will list all of them with a description:</p>

<ul>
  <li>Registers: used to represent the registers from Dalvik.</li>
  <li>Temporal registers: used as an intermediate storage for operations in the expressions.</li>
  <li>Constant Integers: integer values used, for example, in binary operations or comparisons.</li>
  <li>Memory: addresses of memory, including an accessed offset.</li>
  <li>String: a constant string value.</li>
  <li>Callee: a method called by the call instruction from the expressions.</li>
  <li>Field: a field from a Java-like language, the field contains information like the class it belongs, the name of the field, the type, etc.</li>
  <li>Class: a Java-like language class, with the name of the class.</li>
  <li>Fundamental: it represents the fundamental values available in a Java-like language.</li>
</ul>

<h5 id="summary-of-the-ir-instructions">Summary of the IR instructions</h5>

<p>Next I show a summary of the IR:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/Mjolnir.png">
        <img src="/assets/images/kunai_ir/Mjolnir.png" />
    </a>
    <figcaption style="text-align: center;">Structure of MjolnIR.</figcaption>
</figure>

<p>In this image, I include all the statements from the IR, together with that in the bottom of the image we have what will be later explained, the lifter from Dalvik to MjolnIR. The lifter generate <code class="language-plaintext highlighter-rouge">IRGraphs</code> that contains <code class="language-plaintext highlighter-rouge">IRBlocks</code> which contain a list of <code class="language-plaintext highlighter-rouge">IRStmnt</code>s. Finally, from an <code class="language-plaintext highlighter-rouge">IRGraph</code>, an SSA form can be obtained, I will explain the algorithm used later. As part of the original idea, an optimizer was going to be written.</p>

<h4 id="implementation">Implementation</h4>

<p>The idea behind this post is not only providing a theoretical view like you can see in a compiler’s book, but also to provide a real life implementation of such an IR, and an explanation of it’s implementation. After explaining each one of the instructions, I will explain the different algorithms used for manipulating the CFG.</p>

<p>One clarification before starting, from now on I will use the following notation, I write the name of the classes using uppercase for the first character of the name, and in case of the IR all the classes start with <code class="language-plaintext highlighter-rouge">IR</code> followed by the name of the component that it represents (for example <code class="language-plaintext highlighter-rouge">IRStmnt</code>). Most of these classes have their version as a smart pointer, the name of the smart pointer type is the same as its class but in lowercase and followed by <code class="language-plaintext highlighter-rouge">_t</code> (for example <code class="language-plaintext highlighter-rouge">IRBlock</code> -&gt; <code class="language-plaintext highlighter-rouge">irblock_t</code>). For the name of the variables and the name of the functions, I use snake case.</p>

<h5 id="irgraph-implementation"><em>IRGraph</em> Implementation</h5>

<p>Although previously I wrote the BNF from <code class="language-plaintext highlighter-rouge">IRGraph</code>, here I will explain the implementation from the class.</p>

<p>First of all, for the graph we will change the notation and instead of having blocks or a pair of blocks, we will have nodes and edges. In <em>C++</em> we will do this with <code class="language-plaintext highlighter-rouge">using</code> to give another name to the data types:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">Nodes</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">Edge</span>  <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">Edges</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Edge</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">Paths</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;&gt;</span><span class="p">;</span>
</code></pre></div></div>

<p>Here we can see that the nodes are a vector of blocks, and the edges are a pair of blocks, and edges just a vector of edge. Finally, for some algorithms we will use Paths, which are a list of blocks.</p>

<p>Now we can move to see the implementation of a graph. I will not paste the implementation of the functions as I will explain some implementations later in depth, and also the whole code will be included in a repository with all the code.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRGraph</span> <span class="p">{</span>
    <span class="n">IRGraph</span><span class="p">();</span>
    <span class="o">~</span><span class="n">IRGraph</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="kt">bool</span> <span class="n">add_node</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">add_edge</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">src</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">dst</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">add_uniq_edge</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">src</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">dst</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">add_block_to_sucessors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">successor</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">add_block_to_predecessors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">predecessor</span><span class="p">);</span>
    <span class="n">Nodes</span><span class="o">&amp;</span> <span class="n">get_nodes</span><span class="p">();</span>
    <span class="n">Edges</span><span class="o">&amp;</span> <span class="n">get_edges</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">get_node_by_start_idx</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">idx</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">merge_graph</span><span class="p">(</span><span class="n">irgraph_t</span> <span class="n">graph</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">del_edge</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">src</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">dst</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">del_node</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">delete_block_from_sucessors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">block</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">delete_block_from_precessors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">block</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">get_leaves</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">get_heads</span><span class="p">();</span>
    <span class="n">Paths</span> <span class="n">find_path</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">src</span><span class="p">,</span>
                    <span class="n">irblock_t</span> <span class="n">dst</span><span class="p">,</span>
                    <span class="kt">size_t</span> <span class="n">cycles_count</span><span class="p">,</span>
                    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="kt">size_t</span><span class="o">&gt;</span> <span class="n">done</span><span class="p">);</span>
    <span class="n">Paths</span> <span class="n">find_path_from_src</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">src</span><span class="p">,</span>
                                <span class="n">irblock_t</span> <span class="n">dst</span><span class="p">,</span>
                                <span class="kt">size_t</span> <span class="n">cycles_count</span><span class="p">,</span>
                                <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="kt">size_t</span><span class="o">&gt;</span> <span class="n">done</span><span class="p">);</span>
    <span class="n">Nodes</span> <span class="n">reachable_sons</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">);</span>
    <span class="n">Nodes</span> <span class="n">reachable_parents</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">leaf</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">compute_dominators</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">compute_postdominators</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">leaf</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">compute_immediate_dominators</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">compute_immediate_postdominators</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;&gt;</span> <span class="n">compute_dominance_frontier</span><span class="p">();</span>
    <span class="n">irgraph_t</span> <span class="n">copy</span><span class="p">();</span>
    <span class="c1">// node information</span>
    <span class="kt">size_t</span> <span class="n">get_number_of_successors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">);</span>
    <span class="n">Nodes</span><span class="o">&amp;</span> <span class="n">get_successors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">);</span>
    <span class="kt">size_t</span> <span class="n">get_number_of_predecessors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">);</span>
    <span class="n">Nodes</span><span class="o">&amp;</span> <span class="n">get_predecessors</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">);</span>
    <span class="n">node_type_t</span> <span class="n">get_type_of_node</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">node</span><span class="p">);</span>
    <span class="c1">// algorithms from Advanced Compiler Design and Implementation</span>
    <span class="n">Nodes</span> <span class="n">reachable_nodes_forward</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">);</span>
    <span class="n">Nodes</span> <span class="n">reachable_nodes_backward</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">leaf</span><span class="p">);</span>
    <span class="n">Nodes</span> <span class="n">build_ebb</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">r</span><span class="p">);</span>
    <span class="n">Nodes</span> <span class="n">Depth_First_Search</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">);</span>
    <span class="n">Nodes</span> <span class="n">Breadth_First_Search</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">generate_dot_file</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">generate_dominator_tree</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">);</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">get_cyclomatic_complexity</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">set_last_temporal</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">last_temporal</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">get_last_temporal</span><span class="p">();</span>
    
    <span class="nl">private:</span>
    <span class="n">Nodes</span> <span class="n">nodes</span><span class="p">;</span>
    <span class="n">Edges</span> <span class="n">edges</span><span class="p">;</span>

    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">successors</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">predecessors</span><span class="p">;</span>
    
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">cyclomatic_complexity</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">last_temporal</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As we can see, the graph contains the nodes which are a list of blocks, and the edges which are pairs of nodes (blocks connected through the control-flow). For each node, we store a list of successors and predecessors. And finally, some auxiliary variables, like the cyclomatic complexity of that function, and a variable that stores the last assigned temporal register.</p>

<p>For the graph, we have common utilities for adding blocks, removing them, connecting those blocks through edges, etc. But also other utilities not so common like: <code class="language-plaintext highlighter-rouge">get_leaves</code> to get nodes without successors, <code class="language-plaintext highlighter-rouge">get_heads</code> to get nodes without predecessors, <code class="language-plaintext highlighter-rouge">find_path</code> to find a connection between two blocks in the graph searching backwards, <code class="language-plaintext highlighter-rouge">find_path_from_src</code> to find a connection between two blocks in the graph searching forward, <code class="language-plaintext highlighter-rouge">reachable_*</code> that is used to get sons or parents, and others that implement common algorithms in graphs. For the last algorithms, I will explain them in-depth discussing the implementation code and the algorithm used.</p>

<h5 id="irblock-implementation"><code class="language-plaintext highlighter-rouge">IRBlock</code> implementation</h5>

<p>Now we can see the code from the basic blocks:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRBlock</span> <span class="p">{</span>
    <span class="n">IRBlock</span><span class="p">();</span>
    <span class="o">~</span><span class="n">IRBlock</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

    <span class="kt">void</span> <span class="n">add_statement_at_beginning</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="n">statement</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">append_statement_to_block</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="n">statement</span><span class="p">);</span>
    <span class="kt">bool</span> <span class="n">delete_statement_by_position</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">pos</span><span class="p">);</span>
    <span class="kt">size_t</span> <span class="n">get_number_of_statements</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">get_statements</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">set_start_idx</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">start_idx</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">set_end_idx</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">end_idx</span><span class="p">);</span>
    <span class="kt">uint64_t</span> <span class="n">get_start_idx</span><span class="p">();</span>
    <span class="kt">uint64_t</span> <span class="n">get_end_idx</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_name</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">set_phi_node</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">clear_phi_node</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">contains_phi_node</span><span class="p">()</span>
    
    <span class="nl">private:</span>
    <span class="kt">bool</span> <span class="n">phi_node</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
    <span class="c1">//! starting idx and last idx (used for jump calculation)</span>
    <span class="kt">uint64_t</span> <span class="n">start_idx</span><span class="p">,</span> <span class="n">end_idx</span><span class="p">;</span>
    <span class="c1">//! statements from the basic block.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;</span> <span class="n">block_statements</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The basic blocks do not contain much code, they just keep the first and the last index of their instructions, and information to know if a phi instruction exists in the block (for an explanation about the Phi instructions you can go to <code class="language-plaintext highlighter-rouge">BNF</code> section). Finally, the block contains a list of instructions belonging to that block. The included functions are just utilities for inserting instructions, deleting instructions, etc.</p>

<h5 id="irstmnt-implementation"><code class="language-plaintext highlighter-rouge">IRStmnt</code> implementation</h5>

<p>Now, we can see the implementation of the statements, as I previously said, the statements are the root of all the instructions (including the basic blocks). The statement class store also the enum with the type of the statements:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">stmnt_type_t</span>
<span class="p">{</span>
    <span class="n">UJMP_STMNT_T</span><span class="p">,</span>
    <span class="n">CJMP_STMNT_T</span><span class="p">,</span>
    <span class="n">RET_STMNT_T</span><span class="p">,</span>
    <span class="n">NOP_STMNT_T</span><span class="p">,</span>
    <span class="n">SWITCH_STMNT_T</span><span class="p">,</span>
    <span class="n">EXPR_STMNT_T</span><span class="p">,</span>
    <span class="n">NONE_STMNT_T</span> <span class="o">=</span> <span class="mi">99</span> <span class="c1">// used to finish the chain of statements</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Also, we have an enum for all the operations, I included this enum as part of <code class="language-plaintext highlighter-rouge">IRStmnt</code> class too, so we can check which operation we are working with if we have an <code class="language-plaintext highlighter-rouge">IRStmnt</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">op_type_t</span>
<span class="p">{</span>
    <span class="n">UJMP_OP_T</span><span class="p">,</span>
    <span class="n">CJMP_OP_T</span><span class="p">,</span>
    <span class="n">RET_OP_T</span><span class="p">,</span>
    <span class="n">NOP_OP_T</span><span class="p">,</span>
    <span class="n">SWITCH_OP_T</span><span class="p">,</span>
    <span class="n">EXPR_OP_T</span><span class="p">,</span>
    <span class="n">BINOP_OP_T</span><span class="p">,</span>
    <span class="n">UNARYOP_OP_T</span><span class="p">,</span>
    <span class="n">ASSIGN_OP_T</span><span class="p">,</span>
    <span class="n">PHI_OP_T</span><span class="p">,</span>
    <span class="n">CALL_OP_T</span><span class="p">,</span>
    <span class="n">OP_T_OP_T</span><span class="p">,</span>
    <span class="n">LOAD_OP_T</span><span class="p">,</span>
    <span class="n">STORE_OP_T</span><span class="p">,</span>
    <span class="n">ZCOMP_OP_T</span><span class="p">,</span>
    <span class="n">BCOMP_OP_T</span><span class="p">,</span>
    <span class="n">NEW_OP_T</span><span class="p">,</span>
    <span class="n">ALLOCA_OP_T</span><span class="p">,</span>
    <span class="n">TYPE_OP_T</span><span class="p">,</span>
    <span class="n">REGISTER_OP_T</span><span class="p">,</span>
    <span class="n">TEMP_REGISTER_OP_T</span><span class="p">,</span>
    <span class="n">CONST_INT_OP_T</span><span class="p">,</span>
    <span class="n">CONST_FLOAT_OP_T</span><span class="p">,</span>
    <span class="n">FIELD_OP_T</span><span class="p">,</span>
    <span class="n">MEM_OP_T</span><span class="p">,</span>
    <span class="n">STRING_OP_T</span><span class="p">,</span>
    <span class="n">CLASS_OP_T</span><span class="p">,</span>
    <span class="n">CALLEE_OP_T</span><span class="p">,</span>
    <span class="n">FUNDAMENTAL_OP_T</span><span class="p">,</span>
    <span class="n">NONE_OP_T</span> <span class="o">=</span> <span class="mi">99</span> <span class="c1">// used to finish the chain of statements</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Having <code class="language-plaintext highlighter-rouge">IRStmnt</code> as the top of the classes allows to provide it as a value for many parameters, or for variables, then we can cast the pointers in order to work with different classes. Maybe using classes and inheritance is not the best way to generate the IR instructions, but it was the one I had in mind when I thought about providing statements as part of the other instructions.</p>

<p>Now we will see the <code class="language-plaintext highlighter-rouge">IRStmnt</code> class:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRStmnt</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRStmnt</span><span class="p">(</span><span class="n">stmnt_type_t</span> <span class="n">stmnt_type</span><span class="p">,</span> <span class="n">op_type_t</span> <span class="n">op_type</span><span class="p">);</span>
    <span class="k">virtual</span> <span class="o">~</span><span class="n">IRStmnt</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">stmnt_type_t</span> <span class="n">get_statement_type</span><span class="p">();</span>
    <span class="n">op_type_t</span> <span class="n">get_op_type</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">get_use_def_chain</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;&gt;</span> <span class="o">&amp;</span><span class="n">get_def_use_chains</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;</span> <span class="o">*&gt;</span> <span class="n">get_def_use_chain_by_value</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">value</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">add_instr_to_use_def_chain</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="n">instr</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">add_instr_to_def_use_chain</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">var</span><span class="p">,</span> <span class="n">irstmnt_t</span> <span class="n">instr</span><span class="p">);</span>
    <span class="kt">void</span> <span class="n">invalidate_chains</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">invalidate_use_def_chain</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">invalidate_def_use_chains</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">print_use_def_and_def_use_chain</span><span class="p">();</span>

<span class="nl">private:</span>
    <span class="c1">//! Type of the statement.</span>
    <span class="n">stmnt_type_t</span> <span class="n">stmnt_type</span><span class="p">;</span>
    <span class="c1">//! Op type</span>
    <span class="n">op_type_t</span> <span class="n">op_type</span><span class="p">;</span>

    <span class="c1">//! Vectors used for use-def and def-use chains</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;</span> <span class="n">use_def_chain</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;&gt;</span> <span class="n">def_use_chains</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>This code represents the base of all the other instructions. As we can see, we have a couple of getters to know what kind the statement is, or what kind of operation it is. And then one of the most important parts. MjolnIR implemented both <code class="language-plaintext highlighter-rouge">def-use</code> and <code class="language-plaintext highlighter-rouge">use-def</code> chains, these are two lists that for each variable (register), it provides where the register is defined, and where it is used. Later I will provide a better description and the implementation of these algorithms. We have getters, setters and also functions to invalidate those chains.</p>

<h6 id="irujmp-implementation"><code class="language-plaintext highlighter-rouge">IRUJmp</code> implementation</h6>

<p>Let’s see the implementation of an unconditional jump:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRUJmp</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRStmnt</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRUJmp</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">target</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRUJmp</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="kt">void</span> <span class="n">set_jump_target</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">target</span><span class="p">);</span>
    <span class="n">irblock_t</span> <span class="n">get_jump_target</span><span class="p">();</span>
    <span class="kt">uint64_t</span> <span class="n">get_jump_addr</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>

<span class="nl">private:</span>
    <span class="c1">//! offset or address of target</span>
    <span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">;</span>
    <span class="c1">//! target where the jump will fall</span>
    <span class="n">irblock_t</span> <span class="n">target</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The most important part of this instruction in the way I implemented it is the <code class="language-plaintext highlighter-rouge">target</code>. With this <code class="language-plaintext highlighter-rouge">target</code>, given a basic block, we can know where the block will jump.</p>

<h6 id="ircjmp-implementation"><code class="language-plaintext highlighter-rouge">IRCJmp</code> implementation</h6>

<p>Implementation of the conditional jump:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRCJmp</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRStmnt</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRCJmp</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="n">irstmnt_t</span> <span class="n">condition</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">target</span><span class="p">,</span> <span class="n">irblock_t</span> <span class="n">fallthrough</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRCJmp</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">get_addr</span><span class="p">();</span>
    <span class="n">irstmnt_t</span> <span class="n">get_condition</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">set_jump_target</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">target</span><span class="p">);</span>
    <span class="n">irblock_t</span> <span class="n">get_jump_target</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">set_fallthrough_Target</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">fallthrough</span><span class="p">);</span>
    <span class="n">irblock_t</span> <span class="n">get_fallthrough_target</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();;</span>
<span class="nl">private:</span>
    <span class="c1">//! offset or address of target</span>
    <span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">;</span>
    <span class="c1">//! Condition for taking the target jump</span>
    <span class="n">irstmnt_t</span> <span class="n">condition</span><span class="p">;</span>
    <span class="c1">//! target where the jump will fall</span>
    <span class="n">irblock_t</span> <span class="n">target</span><span class="p">;</span>
    <span class="c1">//! fallthrough target.</span>
    <span class="n">irblock_t</span> <span class="n">fallthrough</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The implementation is similar to <code class="language-plaintext highlighter-rouge">IRUJmp</code>, but in this case we need two targets, one taken if the condition matches, and another for the fallthrough target. The condition is provided as an <code class="language-plaintext highlighter-rouge">IRStmnt</code> so any expression or type can be given as a condition (probably in a better implementation, that condition should be restricted to a few types or expressions).</p>

<h6 id="irret-implementation"><code class="language-plaintext highlighter-rouge">IRRet</code> implementation</h6>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRRet</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRStmnt</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRRet</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="n">ret_value</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRRet</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irstmnt_t</span> <span class="n">get_return_value</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
<span class="nl">private:</span>
    <span class="c1">//! Returned value, commonly a NONE IRType, or an IRReg.</span>
    <span class="n">irstmnt_t</span> <span class="n">ret_value</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>A return instruction can optionally have a return value. A return instruction creates a <code class="language-plaintext highlighter-rouge">leaf</code> node, these are nodes that terminate the graph.</p>

<h6 id="irnop-implementation"><code class="language-plaintext highlighter-rouge">IRNop</code> implementation</h6>

<p>The nop instruction doesn’t receive any parameter, and can be used to create empty blocks (blocks that do nothing). So its implementation is pretty simple:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRRet</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRStmnt</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRRet</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="n">ret_value</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRRet</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irstmnt_t</span> <span class="n">get_return_value</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
<span class="nl">private:</span>
    <span class="c1">//! Returned value, commonly a NONE IRType, or an IRReg.</span>
    <span class="n">irstmnt_t</span> <span class="n">ret_value</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irswitch-implementation"><code class="language-plaintext highlighter-rouge">IRSwitch</code> implementation</h6>

<p>The last type of jump is the switch instruction; switch allows given an expression, jumps to different blocks.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRSwitch</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRStmnt</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRSwitch</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int32_t</span><span class="o">&gt;</span> <span class="n">offsets</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">condition</span><span class="p">,</span>
                <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int32_t</span><span class="o">&gt;</span> <span class="n">constants_checks</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRSwitch</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int32_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">get_offsets</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_condition</span><span class="p">();</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int32_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">get_constants_checks</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>

<span class="nl">private:</span>
    <span class="c1">//! switch offsets where instruction will jump.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int32_t</span><span class="o">&gt;</span> <span class="n">offsets</span><span class="p">;</span>
    <span class="c1">//! condition taken to decide where to jump</span>
    <span class="n">irexpr_t</span> <span class="n">condition</span><span class="p">;</span>
    <span class="c1">//! conditions checked during switch.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int32_t</span><span class="o">&gt;</span> <span class="n">constants_checks</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>We have a list of offsets and a list of checks for the <code class="language-plaintext highlighter-rouge">case</code> blocks from the switch statement. For the condition value, we have an expression (commonly a temporal register).</p>

<h5 id="irexpr-implementation"><code class="language-plaintext highlighter-rouge">IRExpr</code> implementation</h5>

<p>Although the <code class="language-plaintext highlighter-rouge">IRExpr</code> instruction does not have itself a long codebase, it is the base class for all the expressions in MjolnIR, and it contains an enum to specify the type of expression we are working with:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">expr_type_t</span>
<span class="p">{</span>
    <span class="n">BINOP_EXPR_T</span><span class="p">,</span>
    <span class="n">UNARYOP_EXPR_T</span><span class="p">,</span>
    <span class="n">ASSIGN_EXPR_T</span><span class="p">,</span>
    <span class="n">PHI_EXPR_T</span><span class="p">,</span>
    <span class="n">CALL_EXPR_T</span><span class="p">,</span>
    <span class="n">TYPE_EXPR_T</span><span class="p">,</span>
    <span class="n">LOAD_EXPR_T</span><span class="p">,</span>
    <span class="n">STORE_EXPR_T</span><span class="p">,</span>
    <span class="n">ZCOMP_EXPR_T</span><span class="p">,</span>
    <span class="n">BCOMP_EXPR_T</span><span class="p">,</span>
    <span class="n">NEW_EXPR_T</span><span class="p">,</span>
    <span class="n">ALLOCA_EXPR_T</span><span class="p">,</span>
    <span class="n">NONE_EXPR_T</span> <span class="o">=</span> <span class="mi">99</span> <span class="c1">// used to finish the expressions</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Finally, the code from the <code class="language-plaintext highlighter-rouge">IRExpr</code> class, contains the code that other expressions will need to create:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRExpr</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRStmnt</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRExpr</span><span class="p">(</span><span class="n">expr_type_t</span> <span class="n">type</span><span class="p">,</span> <span class="n">op_type_t</span> <span class="n">op_type</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRExpr</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">expr_type_t</span> <span class="n">get_expression_type</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">irexpr</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRExpr</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRExpr</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! ir expression as string</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">ir_expr_str</span><span class="p">;</span>

    <span class="c1">//! expression type</span>
    <span class="n">expr_type_t</span> <span class="n">type</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irbinop-implementation"><code class="language-plaintext highlighter-rouge">IRBinOp</code> implementation</h6>

<p>One of the most important operations are binary operations, we have different mathematical operations we do with two operators, and then we store the result in another expression (commonly a register or a temporal register). This class is also the enum of the binary operations:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">bin_op_t</span>
<span class="p">{</span>
    <span class="c1">// common arithmetic instructions</span>
    <span class="n">ADD_OP_T</span><span class="p">,</span>
    <span class="n">SUB_OP_T</span><span class="p">,</span>
    <span class="n">S_MUL_OP_T</span><span class="p">,</span>
    <span class="n">U_MUL_OP_T</span><span class="p">,</span>
    <span class="n">S_DIV_OP_T</span><span class="p">,</span>
    <span class="n">U_DIV_OP_T</span><span class="p">,</span>
    <span class="n">MOD_OP_T</span><span class="p">,</span>
    <span class="c1">// common logic instructions</span>
    <span class="n">AND_OP_T</span><span class="p">,</span>
    <span class="n">XOR_OP_T</span><span class="p">,</span>
    <span class="n">OR_OP_T</span><span class="p">,</span>
    <span class="n">SHL_OP_T</span><span class="p">,</span>
    <span class="n">SHR_OP_T</span><span class="p">,</span>
    <span class="n">USHR_OP_T</span><span class="p">,</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The implementation includes the two operands as expressions, and finally another expression as the place where to store the result</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRBinOp</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRBinOp</span><span class="p">(</span><span class="n">bin_op_t</span> <span class="n">bin_op_type</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">op1</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">op2</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRBinOp</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">bin_op_t</span> <span class="n">get_bin_op_type</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_result</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_op1</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_op2</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irbinop_t</span> <span class="n">irbinop</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRBinOp</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRBinOp</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! type of binary operation</span>
    <span class="n">bin_op_t</span> <span class="n">bin_op_type</span><span class="p">;</span>
    <span class="c1">//! IRBinOp =&gt;  IRExpr(result) = IRExpr(op1) &lt;binop&gt; IRExpr(op2)</span>
    <span class="c1">//! for the result we will have an IRExpr too.</span>
    <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">;</span>
    <span class="c1">//! now each one of the operators</span>
    <span class="n">irexpr_t</span> <span class="n">op1</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">op2</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irunaryop-implementation"><code class="language-plaintext highlighter-rouge">IRUnaryOp</code> implementation</h6>

<p>Similar as the previous operation, we have types of unary operations:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">unary_op_t</span>
<span class="p">{</span>
    <span class="n">NONE_UNARY_OP_T</span><span class="p">,</span>
    <span class="n">INC_OP_T</span><span class="p">,</span>
    <span class="n">DEC_OP_T</span><span class="p">,</span>
    <span class="n">NOT_OP_T</span><span class="p">,</span>
    <span class="n">NEG_OP_T</span><span class="p">,</span>
    <span class="n">CAST_OP_T</span><span class="p">,</span>  <span class="c1">// maybe not used in binary</span>
    <span class="n">Z_EXT_OP_T</span><span class="p">,</span> <span class="c1">// zero extend</span>
    <span class="n">S_EXT_OP_T</span>  <span class="c1">// sign extend</span>
<span class="p">};</span>
</code></pre></div></div>

<p>And because we have a cast operation, we have different casting operation enum values:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">cast_type_t</span>
<span class="p">{</span>
    <span class="n">NONE_CAST</span><span class="p">,</span>
    <span class="n">TO_BYTE</span><span class="p">,</span>
    <span class="n">TO_CHAR</span><span class="p">,</span>
    <span class="n">TO_SHORT</span><span class="p">,</span>
    <span class="n">TO_INT</span><span class="p">,</span>
    <span class="n">TO_LONG</span><span class="p">,</span>
    <span class="n">TO_FLOAT</span><span class="p">,</span>
    <span class="n">TO_DOUBLE</span><span class="p">,</span>
    <span class="n">TO_ADDR</span><span class="p">,</span>
    <span class="n">TO_BOOLEAN</span><span class="p">,</span>
    <span class="n">TO_CLASS</span><span class="p">,</span>
    <span class="n">TO_VOID</span><span class="p">,</span>
    <span class="n">TO_ARRAY</span><span class="p">,</span>
<span class="p">};</span>
</code></pre></div></div>

<p>As part of the implementation, we have a normal constructor that is used to initialize the unary operations, and in case of cast operation, we have another constructor that also initializes the type of cast operation. Also, if the cast is to a class, we can specify the name of the class we are casting too:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRUnaryOp</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRUnaryOp</span><span class="p">(</span><span class="n">unary_op_t</span> <span class="n">unary_op_type</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">op</span><span class="p">);</span>
    <span class="cm">/**
     * @param cast_type: instruction is cast, specify type of cast.
     */</span>
    <span class="n">IRUnaryOp</span><span class="p">(</span><span class="n">unary_op_t</span> <span class="n">unary_op_type</span><span class="p">,</span>
                <span class="n">cast_type_t</span> <span class="n">cast_type</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">op</span><span class="p">);</span>
    <span class="cm">/**
     * @param cast_type: instruction is cast, specify type of cast.
     * @param class_name: if cast is TO_CLASS, specify the name of the class.
     */</span>
    <span class="n">IRUnaryOp</span><span class="p">(</span><span class="n">unary_op_t</span> <span class="n">unary_op_type</span><span class="p">,</span>
                <span class="n">cast_type_t</span> <span class="n">cast_type</span><span class="p">,</span>
                <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">op</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRUnaryOp</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">unary_op_t</span> <span class="n">get_unary_op_type</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_result</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_op</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">set_cast_type</span><span class="p">(</span><span class="n">cast_type_t</span> <span class="n">cast_type</span><span class="p">);</span>
    <span class="n">cast_type_t</span> <span class="n">get_cast_type</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_class_cast</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irunaryop_t</span> <span class="n">irunaryop</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRUnaryOp</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRUnaryOp</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! type of unary operation </span>
    <span class="n">unary_op_t</span> <span class="n">unary_op_type</span><span class="p">;</span>
    <span class="c1">//! used for casting operations</span>
    <span class="n">cast_type_t</span> <span class="n">cast_type</span><span class="p">;</span>
    <span class="c1">//! Class casted to</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">;</span>
    <span class="c1">//! IRUnaryOp =&gt; IRExpr(result) = &lt;unaryop&gt; IRExpr(op)</span>
    <span class="c1">//! an IRExpr for where the result is stored.</span>
    <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">;</span>
    <span class="c1">// operator</span>
    <span class="n">irexpr_t</span> <span class="n">op</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The operand and the result are two expressions (commonly are registers or temporal registers).</p>

<h6 id="irassign-implementation"><code class="language-plaintext highlighter-rouge">IRAssign</code> implementation</h6>

<p>The implementation of this operation is similar to the previous one, since we have only one operand and one result. But conceptually it is very different because this operation is mostly used to move values between registers (registers/temporal registers). So instead of operand and result, we have source and destination. This instruction shouldn’t be used to move from or to memory, since we already have load and store for that.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRAssign</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRAssign</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRAssign</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_destination</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_source</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irassign_t</span> <span class="n">irassign</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRAssign</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRAssign</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! destination where the value will be stored.</span>
    <span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">;</span>
    <span class="c1">//! source expression from where the value is taken</span>
    <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irphi-implementation"><code class="language-plaintext highlighter-rouge">IRPhi</code> implementation</h6>

<p>This instruction is a special instruction in an IR. An IR does not execute the code, but it represents the code. We have cases where the same variable can come from different paths, and depending on the path where the variable comes, its value is one or another. An example with source code would be like so:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">absolute</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">x</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="o">-</span><span class="n">x</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">x</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">value</span> <span class="o">=</span> <span class="o">-</span><span class="mi">42</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">absValue</span> <span class="o">=</span> <span class="n">absolute</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Absolute value of "</span> <span class="o">&lt;&lt;</span> <span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="s">" is "</span> <span class="o">&lt;&lt;</span> <span class="n">absValue</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>A simplified version of the IR, generated from <code class="language-plaintext highlighter-rouge">absolute</code> and generated with LLVM, would be like so:</p>

<div class="language-llvm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">define</span> <span class="kt">i32</span> <span class="vg">@absolute</span><span class="p">(</span><span class="kt">i32</span> <span class="nv">%x</span><span class="p">)</span> <span class="vg">#0</span> <span class="p">{</span>
<span class="nl">entry:</span>
  <span class="nv">%cmp</span> <span class="p">=</span> <span class="k">icmp</span> <span class="k">slt</span> <span class="kt">i32</span> <span class="nv">%x</span><span class="p">,</span> <span class="m">0</span>
  <span class="k">br</span> <span class="kt">i1</span> <span class="nv">%cmp</span><span class="p">,</span> <span class="kt">label</span> <span class="nv">%if.then</span><span class="p">,</span> <span class="kt">label</span> <span class="nv">%if.end</span>

<span class="nl">if.then:</span>                                          <span class="c1">; preds = %entry</span>
  <span class="nv">%neg</span> <span class="p">=</span> <span class="k">sub</span> <span class="k">nsw</span> <span class="kt">i32</span> <span class="m">0</span><span class="p">,</span> <span class="nv">%x</span>
  <span class="k">br</span> <span class="kt">label</span> <span class="nv">%if.end</span>

<span class="nl">if.end:</span>                                           <span class="c1">; preds = %if.then, %entry</span>
  <span class="nv">%retval.0</span> <span class="p">=</span> <span class="k">phi</span> <span class="kt">i32</span> <span class="p">[</span> <span class="nv">%x</span><span class="p">,</span> <span class="nv">%entry</span> <span class="p">],</span> <span class="p">[</span> <span class="nv">%neg</span><span class="p">,</span> <span class="nv">%if.then</span> <span class="p">]</span>
  <span class="k">ret</span> <span class="kt">i32</span> <span class="nv">%retval.0</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We have a <code class="language-plaintext highlighter-rouge">phi</code> instruction that, depending on what the last executed incoming block was, the value of <code class="language-plaintext highlighter-rouge">%retval.0</code> will be <code class="language-plaintext highlighter-rouge">%x</code> if the code came from <code class="language-plaintext highlighter-rouge">%entry</code>, or <code class="language-plaintext highlighter-rouge">%neg</code> if it came from <code class="language-plaintext highlighter-rouge">%if.then</code>.</p>

<p>My implementation includes a map, the map has as a key which identifies the block from where the variable comes from, and as value the expression with the variable (register/temporal register). Finally, we have another expression as result, which will be the final register which will contain the value that will be used from that block.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRPhi</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRPhi</span><span class="p">();</span>
    <span class="o">~</span><span class="n">IRPhi</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">uint32_t</span><span class="p">,</span> <span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">get_params</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">add_param</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">param</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">id</span><span class="p">);</span>
    <span class="n">irexpr_t</span> <span class="n">get_result</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">add_result</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">result</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irphi_t</span> <span class="n">irphi</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRPhi</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRPhi</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">uint32_t</span><span class="p">,</span> <span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="n">params</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="ircall-implementation"><code class="language-plaintext highlighter-rouge">IRCall</code> implementation</h6>

<p>The instruction <code class="language-plaintext highlighter-rouge">IRCall</code> was designed as a call to different types of functions. I implemented internal calls which are calls to functions in the binary, external calls which would be calls to library functions, and finally syscalls. The previous values are <code class="language-plaintext highlighter-rouge">enum</code> values in the code:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">call_type_t</span>
<span class="p">{</span>
    <span class="n">INTERNAL_CALL_T</span><span class="p">,</span>  <span class="c1">// call to internal component</span>
    <span class="n">EXTERNAL_CALL_T</span><span class="p">,</span>  <span class="c1">// call to external library (example DLL, .so file, external component, etc)</span>
    <span class="n">SYSCALL_T</span><span class="p">,</span>        <span class="c1">// a syscall type</span>
    <span class="n">NONE_CALL_T</span> <span class="o">=</span> <span class="mi">99</span><span class="p">,</span> <span class="c1">// Not specified</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The instruction stores as an <code class="language-plaintext highlighter-rouge">IRExpr</code> a callee, later we will see a type <code class="language-plaintext highlighter-rouge">IRCallee</code> that implements these functions for Java-type languages. Then the instruction also contains a vector for the parameters and an optional return value.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRCall</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRCall</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">callee</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="n">args</span><span class="p">);</span>
    <span class="n">IRCall</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">callee</span><span class="p">,</span>
            <span class="n">call_type_t</span> <span class="n">call_type</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="n">args</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRCall</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_callee</span><span class="p">();</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">get_args</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">set_ret_val</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">ret_val</span><span class="p">);</span>
    <span class="n">irexpr_t</span> <span class="n">get_ret_val</span><span class="p">();</span>
    <span class="n">call_type_t</span> <span class="n">get_call_type</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">ircall_t</span> <span class="n">ircall</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRCall</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRCall</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! Type of call</span>
    <span class="n">call_type_t</span> <span class="n">call_type</span><span class="p">;</span>
    <span class="c1">//! Type representing the function/method called</span>
    <span class="n">irexpr_t</span> <span class="n">callee</span><span class="p">;</span>
    <span class="c1">//! Vector with possible arguments</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="n">args</span><span class="p">;</span>
    <span class="c1">//! Return value (if it's for example a register)</span>
    <span class="n">irexpr_t</span> <span class="n">ret_val</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The return value is optional, since we can have <code class="language-plaintext highlighter-rouge">void</code> return values, and parameters can be an empty vector.</p>

<h6 id="irload--irstore-implementations"><code class="language-plaintext highlighter-rouge">IRLoad</code> &amp; <code class="language-plaintext highlighter-rouge">IRStore</code> implementations</h6>

<p>I will put together these instructions since they represent a same concept. These two instructions are used to operate with memory. In the IR I tried to follow the convention <code class="language-plaintext highlighter-rouge">pcode</code>, and I created these instructions to operate with memory, so instead of working with memory directly in the operations, memory values are loaded in registers or in temporal registers. After that, we can operate with those values. The operations contains a <code class="language-plaintext highlighter-rouge">destination</code> and a <code class="language-plaintext highlighter-rouge">source</code> value expressed as <code class="language-plaintext highlighter-rouge">IRExpr</code> but it also has a size value (the size of the loaded or stored value), and also an index in case the memory is accessed using some index.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRLoad</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRLoad class, this class represent a load from memory (using memory or using register).
     * @param destination: register where the value will be stored.
     * @param source: expression from where the memory will be retrieved.
     * @param size: loaded size.
     * @return void
     */</span>
    <span class="n">IRLoad</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">size</span><span class="p">);</span>
    <span class="cm">/**
     * @brief Constructor of IRLoad class, this class represent a load from memory (using memory or using register).
     * @param destination: register where the value will be stored.
     * @param source: expression from where the memory will be retrieved.
     * @param index: index from the load if this is referenced with an index.
     * @param size: loaded size.
     * @return void
     */</span>
    <span class="n">IRLoad</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">index</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRLoad</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_destination</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_source</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_index</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">get_size</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irload_t</span> <span class="n">irload</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRLoad</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRLoad</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! Register where the memory pointed by a register will be loaded.</span>
    <span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">;</span>
    <span class="c1">//! Expression from where memory is read.</span>
    <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">;</span>
    <span class="c1">//! Index if this is referenced by for example a register.</span>
    <span class="n">irexpr_t</span> <span class="n">index</span><span class="p">;</span>
    <span class="c1">//! Size of loaded value</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">size</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">IRStore</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRStore class, this represent an store to memory instruction.
     * @param destination: Expression where value is written to.
     * @param source: register with the value to be stored.
     * @param size: size of the stored value.
     * @return void
     */</span>
    <span class="n">IRStore</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">size</span><span class="p">);</span>
    <span class="cm">/**
     * @brief Constructor of IRStore class, this represent an store to memory instruction.
     * @param destination: Expression where value is written to.
     * @param source: register with the value to be stored.
     * @param index: index where value is stored.
     * @param size: size of the stored value.
     * @return void
     */</span>
    <span class="n">IRStore</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">index</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRStore</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_destination</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_source</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_index</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">get_size</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irstore_t</span> <span class="n">irstore</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRStore</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRStore</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! Memory pointed by register where value will be stored.</span>
    <span class="n">irexpr_t</span> <span class="n">destination</span><span class="p">;</span>
    <span class="c1">//! Expression with source of value to be stored.</span>
    <span class="n">irexpr_t</span> <span class="n">source</span><span class="p">;</span>
    <span class="c1">//! Index if this is referenced by for example a register.</span>
    <span class="n">irexpr_t</span> <span class="n">index</span><span class="p">;</span>
    <span class="c1">//! Size of stored value</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">size</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irzcomp-implementation"><code class="language-plaintext highlighter-rouge">IRZComp</code> implementation</h6>

<p>Since this IR was mainly implemented for Java-like languages, I implemented an instruction to compare with a zero value. There are different <code class="language-plaintext highlighter-rouge">enum</code> values that will tell the type of comparator:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">zero_comp_t</span>
<span class="p">{</span>
    <span class="n">EQUAL_ZERO_T</span><span class="p">,</span>       <span class="c1">// ==</span>
    <span class="n">NOT_EQUAL_ZERO_T</span><span class="p">,</span>   <span class="c1">// !=</span>
    <span class="n">LOWER_ZERO_T</span><span class="p">,</span>       <span class="c1">// &lt;</span>
    <span class="n">GREATER_EQUAL_ZERO</span><span class="p">,</span> <span class="c1">// &gt;=</span>
    <span class="n">GREATER_ZERO_T</span><span class="p">,</span>     <span class="c1">// &gt;</span>
    <span class="n">LOWER_EQUAL_ZERO</span>    <span class="c1">// &lt;=</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Then the instruction contains a register for the compared operand, and a register for storing the result. In both cases the values are provided as <code class="language-plaintext highlighter-rouge">IRExpr</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRZComp</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRZComp, this is a comparison with zero.
     * @param comp: type of comparison (== or !=).
     * @param result: register or temporal register where result is stored.
     * @param reg: register used in the comparison.
     * @return void
     */</span>
    <span class="n">IRZComp</span><span class="p">(</span><span class="n">zero_comp_t</span> <span class="n">comp</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">reg</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRZComp</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_result</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_reg</span><span class="p">();</span>
    <span class="n">zero_comp_t</span> <span class="n">get_comparison</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irzcomp_t</span> <span class="n">irzcomp</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRZComp</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRZComp</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! Register where result is stored</span>
    <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">;</span>
    <span class="c1">//! Register for comparison with zero.</span>
    <span class="n">irexpr_t</span> <span class="n">reg</span><span class="p">;</span>
    <span class="c1">//! Type of comparison</span>
    <span class="n">zero_comp_t</span> <span class="n">comp</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irbcomp-implementation"><code class="language-plaintext highlighter-rouge">IRBComp</code> implementation</h6>

<p>In the case, we do not compare with zero, but between two registers, we use this instruction. Again we have different types of comparisons:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">comp_t</span>
<span class="p">{</span>
    <span class="n">EQUAL_T</span><span class="p">,</span>         <span class="c1">// ==</span>
    <span class="n">NOT_EQUAL_T</span><span class="p">,</span>     <span class="c1">// !=</span>
    <span class="n">GREATER_T</span><span class="p">,</span>       <span class="c1">// &gt;</span>
    <span class="n">GREATER_EQUAL_T</span><span class="p">,</span> <span class="c1">// &gt;=</span>
    <span class="n">LOWER_T</span><span class="p">,</span>         <span class="c1">// &lt;</span>
    <span class="n">LOWER_EQUAL_T</span><span class="p">,</span>   <span class="c1">// &lt;=</span>
    <span class="n">ABOVE_T</span><span class="p">,</span>         <span class="c1">// (unsigned) &gt;</span>
    <span class="n">ABOVE_EQUAL_T</span><span class="p">,</span>   <span class="c1">// (unsigned) &gt;=</span>
    <span class="n">BELOW_T</span><span class="p">,</span>         <span class="c1">// (unsigned) &lt;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The instruction implementation is almost the same as the previous one, but this time with two registers as operators:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRBComp</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRBComp, this class represent a comparison between two types.
     * @param comp: type of comparison from an enum.
     * @param result: register or temporal register where result is stored.
     * @param reg1: first type where the comparison is applied.
     * @param reg2: second type where the comparison is applied.
     * @return void
     */</span>
    <span class="n">IRBComp</span><span class="p">(</span><span class="n">comp_t</span> <span class="n">comp</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">reg1</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">reg2</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRBComp</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_result</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_reg1</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_reg2</span><span class="p">();</span>
    <span class="n">comp_t</span> <span class="n">get_comparison</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irbcomp_t</span> <span class="n">bcomp</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRBComp</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRBComp</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! register or temporal register where result is stored</span>
    <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">;</span>
    <span class="c1">//! registers used in the comparisons.</span>
    <span class="n">irexpr_t</span> <span class="n">reg1</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">reg2</span><span class="p">;</span>
    <span class="c1">//! Type of comparison</span>
    <span class="n">comp_t</span> <span class="n">comp</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irnew-implementation"><code class="language-plaintext highlighter-rouge">IRNew</code> implementation</h6>

<p>Java-type languages contain a <code class="language-plaintext highlighter-rouge">new</code> instruction for allocating memory for a new object. This instruction contains a result value (which will be a register) and a class instance that will be the type of the new object. We will later see in types the <code class="language-plaintext highlighter-rouge">IRClass</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRNew</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Construct a new IRNew::IRNew object which represents
     *        the creation of an instance of a class.
     *
     * @param result: result register where object is stored.
     * @param class_instance: IRClass object which represent the instance.
     * @return void
     */</span>
    <span class="n">IRNew</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
            <span class="n">irexpr_t</span> <span class="n">class_instance</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRNew</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_result</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_source_class</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">irnew_t</span> <span class="n">new_i</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRNew</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRNew</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! register where the result will be stored.</span>
    <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">;</span>
    <span class="c1">//! class type which will create a new instance.</span>
    <span class="n">irexpr_t</span> <span class="n">class_instance</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="iralloca-implementation"><code class="language-plaintext highlighter-rouge">IRAlloca</code> implementation</h6>

<p>In opposite to a <code class="language-plaintext highlighter-rouge">new</code> instruction, we can allocate memory to store an array. In Java-type languages, the arrays are allocated as objects. <code class="language-plaintext highlighter-rouge">IRAlloca</code> has this purpose, allocating memory for an array. And for that reason <code class="language-plaintext highlighter-rouge">IRAlloca</code> has a size value:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRAlloca</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Construct a new IRAlloca object,  this kind of
     *        expression creates "allocates" memory for an array
     *        having this class will be useful also for allocating
     *        memory in other architectures.
     *
     * @param result register or address where data will be stored
     * @param type_instance type to create an array
     * @param size size of the given array
     */</span>
    <span class="n">IRAlloca</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="n">result</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">type_instance</span><span class="p">,</span>
                <span class="n">irexpr_t</span> <span class="n">size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRAlloca</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">irexpr_t</span> <span class="n">get_result</span><span class="p">()</span>
    <span class="n">irexpr_t</span> <span class="n">get_source_type</span><span class="p">();</span>
    <span class="n">irexpr_t</span> <span class="n">get_size</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equals</span><span class="p">(</span><span class="n">iralloca_t</span> <span class="n">alloca</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRAlloca</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRAlloca</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! register or variable where result will be stored.</span>
    <span class="n">irexpr_t</span> <span class="n">result</span><span class="p">;</span>
    <span class="c1">//! type which it will create a new instance</span>
    <span class="n">irexpr_t</span> <span class="n">type_instance</span><span class="p">;</span>
    <span class="c1">//! size of the allocated space</span>
    <span class="n">irexpr_t</span> <span class="n">size</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h5 id="irtype-implementation"><code class="language-plaintext highlighter-rouge">IRType</code> implementation</h5>

<p>Finally, we arrive to the objects that represent the operands of the operations, the memory, the classes, the fields, etc. For that reason, <code class="language-plaintext highlighter-rouge">IRType</code> contains an enum that specify the type:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">type_t</span>
<span class="p">{</span>
    <span class="n">REGISTER_TYPE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
    <span class="n">TEMP_REGISTER_TYPE</span><span class="p">,</span>
    <span class="n">CONST_INT_TYPE</span><span class="p">,</span>
    <span class="n">CONST_FLOAT_TYPE</span><span class="p">,</span>
    <span class="n">FIELD_TYPE</span><span class="p">,</span>
    <span class="n">MEM_TYPE</span><span class="p">,</span>
    <span class="n">STRING_TYPE</span><span class="p">,</span>
    <span class="n">CLASS_TYPE</span><span class="p">,</span>
    <span class="n">CALLEE_TYPE</span><span class="p">,</span>
    <span class="n">FUNDAMENTAL_TYPE</span><span class="p">,</span>
    <span class="n">NONE_TYPE</span> <span class="o">=</span> <span class="mi">99</span>
<span class="p">};</span>
</code></pre></div></div>

<p>An idea I had was to store the order of the memory access. Commonly architectures like x86, x86-64 stores the memory in a format known as <code class="language-plaintext highlighter-rouge">little-endian</code>, but other architectures can store the data in <code class="language-plaintext highlighter-rouge">big-endian</code>, even the crazy idea of a <code class="language-plaintext highlighter-rouge">middle-endian</code> exists!!! You can read more about endianness at <a href="https://en.wikipedia.org/wiki/Endianness">wikipedia</a>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">mem_access_t</span>
<span class="p">{</span>
    <span class="n">LE_ACCESS</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="c1">//! little-endian access</span>
    <span class="n">BE_ACCESS</span><span class="p">,</span>     <span class="c1">//! big-endian access</span>
    <span class="n">ME_ACCESS</span><span class="p">,</span>     <span class="c1">//! This shouldn't commonly happen?</span>
    <span class="n">NONE_ACCESS</span> <span class="o">=</span> <span class="mi">99</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The instruction stores the type, a name to represent the type, even a field for annotations to store and show from the type.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRType</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRExpr</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of the IRType, this will be the generic type used for the others.
     * @param type: type of the class.
     * @param op_type: global type of operation
     * @param type_name: name used for representing the type while printing.
     * @param type_size: size of the type in bytes.
     * @return void
     */</span>
    <span class="n">IRType</span><span class="p">(</span><span class="n">type_t</span> <span class="n">type</span><span class="p">,</span> <span class="n">op_type_t</span> <span class="n">op_type</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRType</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_name</span><span class="p">();</span>
    <span class="kt">size_t</span> <span class="n">get_type_size</span><span class="p">();</span>
    <span class="n">type_t</span> <span class="n">get_type</span><span class="p">();</span>
    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="kt">void</span> <span class="n">write_annotations</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">annotations</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">read_annotations</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irtype_t</span> <span class="n">type</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRType</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRType</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! type value as a type_t</span>
    <span class="n">type_t</span> <span class="n">type</span><span class="p">;</span>
    <span class="c1">//! name used to represent the type in IR representation.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">;</span>
    <span class="c1">//! size of the type, this can vary depending on architecture</span>
    <span class="c1">//! and so on.</span>
    <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">;</span>
    <span class="c1">//! annotations are there for you to write whatever you want</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">annotations</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irreg-implementation"><code class="language-plaintext highlighter-rouge">IRReg</code> implementation</h6>

<p>The IRs commonly operate with values or with registers. These are the basic types in the operations. The registers can be those from the architecture using the name of that computer architecture, or like in SSA-form IRs we can use an infinite set of registers. Compilers when they transform from IR to assembly apply different optimizations to reduce the number of registers, and then to assign the registers from the IR, to those from the real machine. In the case of virtual architectures like dalvik, the VM has 64K registers for each called method, since these are virtual registers. The registers of MjolnIR contain an id, and depending on the architecture, the id can represent one register from that architecture or not. Although I didn’t use it, following Triton’s implementation, I created the next types (but I didn’t ever use them…):</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="kt">int</span> <span class="n">x86_arch</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>

<span class="k">enum</span> <span class="n">x86_regs_t</span>
<span class="cm">/**
 * @brief X86 registers, enums for IR, sizes and strings.
 */</span>
<span class="p">{</span>
    <span class="c1">// General purpose registers</span>
    <span class="n">rax</span><span class="p">,</span> <span class="n">eax</span><span class="p">,</span> <span class="n">ax</span><span class="p">,</span> <span class="n">ah</span><span class="p">,</span> <span class="n">al</span><span class="p">,</span>
    <span class="n">rbx</span><span class="p">,</span> <span class="n">ebx</span><span class="p">,</span> <span class="n">bx</span><span class="p">,</span> <span class="n">bh</span><span class="p">,</span> <span class="n">bl</span><span class="p">,</span>
    <span class="n">rcx</span><span class="p">,</span> <span class="n">ecx</span><span class="p">,</span> <span class="n">cx</span><span class="p">,</span> <span class="n">ch</span><span class="p">,</span> <span class="n">cl</span><span class="p">,</span>
    <span class="n">rdx</span><span class="p">,</span> <span class="n">edx</span><span class="p">,</span> <span class="n">dx</span><span class="p">,</span> <span class="n">dh</span><span class="p">,</span> <span class="n">dl</span><span class="p">,</span>
    <span class="c1">// pointer registers</span>
    <span class="n">rdi</span><span class="p">,</span> <span class="n">edi</span><span class="p">,</span> <span class="n">di</span><span class="p">,</span>
    <span class="n">rsi</span><span class="p">,</span> <span class="n">esi</span><span class="p">,</span> <span class="n">si</span><span class="p">,</span>
    <span class="c1">// stack registers</span>
    <span class="n">rbp</span><span class="p">,</span> <span class="n">ebp</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span>
    <span class="n">rsp</span><span class="p">,</span> <span class="n">esp</span><span class="p">,</span> <span class="n">sp</span><span class="p">,</span>
    <span class="c1">// program counter</span>
    <span class="n">rip</span><span class="p">,</span> <span class="n">eip</span><span class="p">,</span> <span class="n">ip</span><span class="p">,</span>
    <span class="c1">// extended registers in x86-64</span>
    <span class="n">r8</span><span class="p">,</span> <span class="n">r8d</span><span class="p">,</span> <span class="n">r8w</span><span class="p">,</span> <span class="n">r8b</span><span class="p">,</span> 
    <span class="n">r9</span><span class="p">,</span> <span class="n">r9d</span><span class="p">,</span> <span class="n">r9w</span><span class="p">,</span> <span class="n">r9b</span><span class="p">,</span> 
    <span class="n">r10</span><span class="p">,</span> <span class="n">r10d</span><span class="p">,</span> <span class="n">r10w</span><span class="p">,</span> <span class="n">r10b</span><span class="p">,</span>
    <span class="n">r11</span><span class="p">,</span> <span class="n">r11d</span><span class="p">,</span> <span class="n">r11w</span><span class="p">,</span> <span class="n">r11b</span><span class="p">,</span> 
    <span class="n">r12</span><span class="p">,</span> <span class="n">r12d</span><span class="p">,</span> <span class="n">r12w</span><span class="p">,</span> <span class="n">r12b</span><span class="p">,</span> 
    <span class="n">r13</span><span class="p">,</span> <span class="n">r13d</span><span class="p">,</span> <span class="n">r13w</span><span class="p">,</span> <span class="n">r13b</span><span class="p">,</span> 
    <span class="n">r14</span><span class="p">,</span> <span class="n">r14d</span><span class="p">,</span> <span class="n">r14w</span><span class="p">,</span> <span class="n">r14b</span><span class="p">,</span> 
    <span class="n">r15</span><span class="p">,</span> <span class="n">r15d</span><span class="p">,</span> <span class="n">r15w</span><span class="p">,</span> <span class="n">r15b</span><span class="p">,</span> 
    <span class="c1">// flags for state representation</span>
    <span class="n">eflags</span><span class="p">,</span>
    <span class="n">mm0</span><span class="p">,</span> <span class="n">mm1</span><span class="p">,</span> <span class="n">mm2</span><span class="p">,</span> <span class="n">mm3</span><span class="p">,</span> <span class="n">mm4</span><span class="p">,</span> <span class="n">mm5</span><span class="p">,</span> <span class="n">mm6</span><span class="p">,</span> <span class="n">mm7</span><span class="p">,</span>
    <span class="n">zmm0</span><span class="p">,</span> <span class="n">zmm1</span><span class="p">,</span> <span class="n">zmm2</span><span class="p">,</span> <span class="n">zmm3</span><span class="p">,</span> <span class="n">zmm4</span><span class="p">,</span> <span class="n">zmm5</span><span class="p">,</span> <span class="n">zmm6</span><span class="p">,</span> 
    <span class="n">zmm7</span><span class="p">,</span> <span class="n">zmm8</span><span class="p">,</span> <span class="n">zmm9</span><span class="p">,</span> <span class="n">zmm10</span><span class="p">,</span> <span class="n">zmm11</span><span class="p">,</span> <span class="n">zmm12</span><span class="p">,</span> <span class="n">zmm13</span><span class="p">,</span> 
    <span class="n">zmm14</span><span class="p">,</span> <span class="n">zmm15</span><span class="p">,</span> <span class="n">zmm16</span><span class="p">,</span> <span class="n">zmm17</span><span class="p">,</span> <span class="n">zmm18</span><span class="p">,</span> <span class="n">zmm19</span><span class="p">,</span> <span class="n">zmm20</span><span class="p">,</span> 
    <span class="n">zmm21</span><span class="p">,</span> <span class="n">zmm22</span><span class="p">,</span> <span class="n">zmm23</span><span class="p">,</span> <span class="n">zmm24</span><span class="p">,</span> <span class="n">zmm25</span><span class="p">,</span> <span class="n">zmm26</span><span class="p">,</span> <span class="n">zmm27</span><span class="p">,</span> 
    <span class="n">zmm28</span><span class="p">,</span> <span class="n">zmm29</span><span class="p">,</span> <span class="n">zmm30</span><span class="p">,</span> <span class="n">zmm31</span><span class="p">,</span> <span class="n">mxcsr</span><span class="p">,</span>
    <span class="n">cr0</span><span class="p">,</span> <span class="n">cr1</span><span class="p">,</span> <span class="n">cr2</span><span class="p">,</span> <span class="n">cr3</span><span class="p">,</span> <span class="n">cr4</span><span class="p">,</span> <span class="n">cr5</span><span class="p">,</span> <span class="n">cr6</span><span class="p">,</span> <span class="n">cr7</span><span class="p">,</span> <span class="n">cr8</span><span class="p">,</span> <span class="n">cr9</span><span class="p">,</span>
    <span class="n">cr10</span><span class="p">,</span> <span class="n">cr11</span><span class="p">,</span> <span class="n">cr12</span><span class="p">,</span> <span class="n">cr13</span><span class="p">,</span> <span class="n">cr14</span><span class="p">,</span> <span class="n">cr15</span><span class="p">,</span>
    <span class="n">cs</span><span class="p">,</span> <span class="n">ds</span><span class="p">,</span> <span class="n">es</span><span class="p">,</span> <span class="n">fs</span><span class="p">,</span> <span class="n">gs</span><span class="p">,</span> <span class="n">ss</span><span class="p">,</span>
    <span class="n">dr0</span><span class="p">,</span> <span class="n">dr1</span><span class="p">,</span> <span class="n">dr2</span><span class="p">,</span> <span class="n">dr3</span><span class="p">,</span> <span class="n">dr6</span><span class="p">,</span> <span class="n">dr7</span>
<span class="p">};</span>

<span class="k">static</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="n">x86_regs_t</span><span class="p">,</span> <span class="kt">size_t</span><span class="o">&gt;</span> <span class="n">x86_regs_size</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">{</span><span class="n">rax</span><span class="p">,</span><span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">eax</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">ax</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">ah</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="n">al</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rbx</span><span class="p">,</span><span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">ebx</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">bx</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">bh</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="n">bl</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rcx</span><span class="p">,</span><span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">ecx</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">cx</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">ch</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="n">cl</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rdx</span><span class="p">,</span><span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">edx</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">dx</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">dh</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span> <span class="p">{</span><span class="n">dl</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rdi</span><span class="p">,</span><span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">edi</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">di</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rsi</span><span class="p">,</span><span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">esi</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">si</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rip</span><span class="p">,</span><span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">eip</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">ip</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r8</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r8d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r8w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r8b</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span> 
    <span class="p">{</span><span class="n">r9</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r9d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r9w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r9b</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r10</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r10d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r10w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r10b</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r11</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r11d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r11w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r11b</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span> 
    <span class="p">{</span><span class="n">r12</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r12d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r12w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r12b</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r13</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r13d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r13w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r13b</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r14</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r14d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r14w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r14b</span><span class="p">,</span><span class="mi">1</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r15</span><span class="p">,</span> <span class="mi">8</span><span class="p">},</span> <span class="p">{</span><span class="n">r15d</span><span class="p">,</span><span class="mi">4</span><span class="p">},</span> <span class="p">{</span><span class="n">r15w</span><span class="p">,</span><span class="mi">2</span><span class="p">},</span> <span class="p">{</span><span class="n">r15b</span><span class="p">,</span><span class="mi">1</span><span class="p">}</span>
<span class="p">};</span>

<span class="k">static</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="n">x86_regs_t</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">x86_regs_name</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">{</span><span class="n">rax</span><span class="p">,</span><span class="s">"rax"</span><span class="p">},</span> <span class="p">{</span><span class="n">eax</span><span class="p">,</span><span class="s">"eax"</span><span class="p">},</span> <span class="p">{</span><span class="n">ax</span><span class="p">,</span><span class="s">"ax"</span><span class="p">},</span> <span class="p">{</span><span class="n">ah</span><span class="p">,</span><span class="s">"ah"</span><span class="p">},</span> <span class="p">{</span><span class="n">al</span><span class="p">,</span><span class="s">"al"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rbx</span><span class="p">,</span><span class="s">"rbx"</span><span class="p">},</span> <span class="p">{</span><span class="n">ebx</span><span class="p">,</span><span class="s">"ebx"</span><span class="p">},</span> <span class="p">{</span><span class="n">bx</span><span class="p">,</span><span class="s">"bx"</span><span class="p">},</span> <span class="p">{</span><span class="n">bh</span><span class="p">,</span><span class="s">"bh"</span><span class="p">},</span> <span class="p">{</span><span class="n">bl</span><span class="p">,</span><span class="s">"bl"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rcx</span><span class="p">,</span><span class="s">"rcx"</span><span class="p">},</span> <span class="p">{</span><span class="n">ecx</span><span class="p">,</span><span class="s">"ecx"</span><span class="p">},</span> <span class="p">{</span><span class="n">cx</span><span class="p">,</span><span class="s">"cx"</span><span class="p">},</span> <span class="p">{</span><span class="n">ch</span><span class="p">,</span><span class="s">"ch"</span><span class="p">},</span> <span class="p">{</span><span class="n">cl</span><span class="p">,</span><span class="s">"cl"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rdx</span><span class="p">,</span><span class="s">"rdx"</span><span class="p">},</span> <span class="p">{</span><span class="n">edx</span><span class="p">,</span><span class="s">"edx"</span><span class="p">},</span> <span class="p">{</span><span class="n">dx</span><span class="p">,</span><span class="s">"dx"</span><span class="p">},</span> <span class="p">{</span><span class="n">dh</span><span class="p">,</span><span class="s">"dh"</span><span class="p">},</span> <span class="p">{</span><span class="n">dl</span><span class="p">,</span><span class="s">"dl"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rdi</span><span class="p">,</span><span class="s">"rdi"</span><span class="p">},</span> <span class="p">{</span><span class="n">edi</span><span class="p">,</span><span class="s">"edi"</span><span class="p">},</span> <span class="p">{</span><span class="n">di</span><span class="p">,</span><span class="s">"di"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rsi</span><span class="p">,</span><span class="s">"rsi"</span><span class="p">},</span> <span class="p">{</span><span class="n">esi</span><span class="p">,</span><span class="s">"esi"</span><span class="p">},</span> <span class="p">{</span><span class="n">si</span><span class="p">,</span><span class="s">"si"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">rip</span><span class="p">,</span><span class="s">"rip"</span><span class="p">},</span> <span class="p">{</span><span class="n">eip</span><span class="p">,</span><span class="s">"eip"</span><span class="p">},</span> <span class="p">{</span><span class="n">ip</span><span class="p">,</span><span class="s">"ip"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r8</span><span class="p">,</span><span class="s">"r8"</span><span class="p">},</span> <span class="p">{</span><span class="n">r8d</span><span class="p">,</span><span class="s">"r8d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r8w</span><span class="p">,</span><span class="s">"r8w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r8b</span><span class="p">,</span><span class="s">"r8b"</span><span class="p">},</span> 
    <span class="p">{</span><span class="n">r9</span><span class="p">,</span><span class="s">"r9"</span><span class="p">},</span> <span class="p">{</span><span class="n">r9d</span><span class="p">,</span><span class="s">"r9d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r9w</span><span class="p">,</span><span class="s">"r9w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r9b</span><span class="p">,</span><span class="s">"r9b"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r10</span><span class="p">,</span><span class="s">"r10"</span><span class="p">},</span> <span class="p">{</span><span class="n">r10d</span><span class="p">,</span><span class="s">"r10d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r10w</span><span class="p">,</span><span class="s">"r10w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r10b</span><span class="p">,</span><span class="s">"r10b"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r11</span><span class="p">,</span><span class="s">"r11"</span><span class="p">},</span> <span class="p">{</span><span class="n">r11d</span><span class="p">,</span><span class="s">"r11d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r11w</span><span class="p">,</span><span class="s">"r11w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r11b</span><span class="p">,</span><span class="s">"r11b"</span><span class="p">},</span> 
    <span class="p">{</span><span class="n">r12</span><span class="p">,</span><span class="s">"r12"</span><span class="p">},</span> <span class="p">{</span><span class="n">r12d</span><span class="p">,</span><span class="s">"r12d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r12w</span><span class="p">,</span><span class="s">"r12w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r12b</span><span class="p">,</span><span class="s">"r12b"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r13</span><span class="p">,</span><span class="s">"r13"</span><span class="p">},</span> <span class="p">{</span><span class="n">r13d</span><span class="p">,</span><span class="s">"r13d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r13w</span><span class="p">,</span><span class="s">"r13w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r13b</span><span class="p">,</span><span class="s">"r13b"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r14</span><span class="p">,</span><span class="s">"r14"</span><span class="p">},</span> <span class="p">{</span><span class="n">r14d</span><span class="p">,</span><span class="s">"r14d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r14w</span><span class="p">,</span><span class="s">"r14w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r14b</span><span class="p">,</span><span class="s">"r14b"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">r15</span><span class="p">,</span><span class="s">"r15"</span><span class="p">},</span> <span class="p">{</span><span class="n">r15d</span><span class="p">,</span><span class="s">"r15d"</span><span class="p">},</span> <span class="p">{</span><span class="n">r15w</span><span class="p">,</span><span class="s">"r15w"</span><span class="p">},</span> <span class="p">{</span><span class="n">r15b</span><span class="p">,</span><span class="s">"r15b"</span><span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The first implementation of MjolnIR wasn’t using an SSA form but directly used the values from Dalvik. Later I implemented the SSA form, and for that the <code class="language-plaintext highlighter-rouge">IRReg</code> contains a <code class="language-plaintext highlighter-rouge">sub_id</code> field, to express the SSA form in the registers:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRReg</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRReg type.
     * @param reg_id: id of the register this can be an enum if is a well known register, or just an id.
     * @param current_arch: curreng architecture to create the register.
     * @param type_name: string for representing the register.
     * @param type_size: size of the register.
     * @return void
     */</span>
    <span class="n">IRReg</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">reg_id</span><span class="p">,</span> <span class="kt">int</span> <span class="n">current_arch</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="cm">/**
     * @brief Constructor of IRReg type.
     * @param reg_id: id of the register this can be an enum if is a well known register, or just an id.
     * @param reg_sub_id: sub id of the register used in the SSA form.
     * @param current_arch: curreng architecture to create the register.
     * @param type_name: string for representing the register.
     * @param type_size: size of the register.
     * @return void
     */</span>
    <span class="n">IRReg</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">reg_id</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">int32_t</span> <span class="n">reg_sub_id</span><span class="p">,</span> <span class="kt">int</span> <span class="n">current_arch</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRReg</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">get_id</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">get_sub_id</span><span class="p">();</span>
    <span class="kt">int</span> <span class="n">get_current_arch</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">same</span><span class="p">(</span><span class="n">irreg_t</span> <span class="n">reg</span><span class="p">);</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irreg_t</span> <span class="n">reg</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRReg</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRReg</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! id of the register, this will be an enum</span>
    <span class="c1">//! in case the arquitecture contains a known set</span>
    <span class="c1">//! of registers, for example x86-64 will have a</span>
    <span class="c1">//! well known set of registers, e.g. EAX, AX, RSP</span>
    <span class="c1">//! RIP, etc.</span>
    <span class="c1">//! Other arquitectures like DEX VM will not have</span>
    <span class="c1">//! an specific set.</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">id</span><span class="p">;</span>
    <span class="c1">//! sub id of the register, this sub id will be used</span>
    <span class="c1">//! in the SSA form, and used to check if a register</span>
    <span class="c1">//! is the same than other.</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">int32_t</span> <span class="n">sub_id</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">current_arch</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irtempreg-implementation"><code class="language-plaintext highlighter-rouge">IRTempReg</code> implementation</h6>

<p>In some cases, the instructions implement intrinsic operands, an IR instead of representing instrinsic operands it can use registers. In MjolnIR for doing so, I implemented temporal registers. For example, if a language uses 3 operands like the next:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">z</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">d</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">z</span><span class="p">;</span>
</code></pre></div></div>

<p>Commonly an IR instruction only contains two operands, and then the result value. For that reason we can use a temporal register to represent the previous sequence of instructions in the next way:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">z</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="n">temp_reg1</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">d</span> <span class="o">=</span> <span class="n">temp_reg1</span> <span class="o">+</span> <span class="n">z</span><span class="p">;</span>
</code></pre></div></div>

<p>Now the instruction only has two operands. For doing these operations, MjolnIR uses <code class="language-plaintext highlighter-rouge">IRTempReg</code> operands:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">class</span> <span class="nc">IRTempReg</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRTempReg type.
     * @param reg_id: id of the register this will be an incremental id.
     * @param type_name: string for representing the register.
     * @param type_size: size of the register.
     * @return void
     */</span>
    <span class="n">IRTempReg</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">reg_id</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRTempReg</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">get_id</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irtempreg_t</span> <span class="n">temp_reg</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRTempReg</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRTempReg</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! This id will be just an incremental number</span>
    <span class="c1">//! as these are temporal registers.</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">id</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irconstint-implementation"><code class="language-plaintext highlighter-rouge">IRConstInt</code> implementation</h6>

<p>This object is just a wrapper for constant integer values. It is also used to store metadata like if the value is signed or not, and the byte order (this maybe was a foolish decision on my side…). Since a possible optimization for obfuscated values was constant folding, I implemented the different operators on the class. The operators internally check if the values are signed or unsigned, and finally return another <code class="language-plaintext highlighter-rouge">IRConstInt</code> with the proper size:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">is_signed</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">int64_t</span> <span class="n">result</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int64_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">value</span><span class="p">)</span> <span class="o">+</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int64_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">value</span><span class="p">);</span>
        <span class="n">IRConstInt</span> <span class="n">res</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">is_signed</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">byte_order</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">get_type_name</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">get_type_size</span><span class="p">());</span>

        <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="kt">uint64_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">value</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="n">value</span><span class="p">;</span>

    <span class="n">IRConstInt</span> <span class="n">res</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">is_signed</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">byte_order</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">get_type_name</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">get_type_size</span><span class="p">());</span>
    <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Next, the implementation of <code class="language-plaintext highlighter-rouge">IRConstInt</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRConstInt</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRConstInt this represent any integer used in the code.
     * @param value: value of the constant integer
     * @param is_signed: is signed value (true) or unsigned (false).
     * @param byte_order: byte order of the value.
     * @param type_name: name used for representing the value.
     * @param type_size: size of the integer.
     * @return void
     */</span>
    <span class="n">IRConstInt</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">value</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">is_signed</span><span class="p">,</span> <span class="n">mem_access_t</span> <span class="n">byte_order</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRConstInt</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="kt">bool</span> <span class="n">get_is_signed</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="kt">uint64_t</span> <span class="n">get_value_unsigned</span><span class="p">();</span>
    <span class="kt">int64_t</span> <span class="n">get_value_signed</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irconstint_t</span> <span class="n">const_int</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">/</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">*</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">%</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">&amp;</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">|</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">^</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">&gt;&gt;</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">++</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">--</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">!</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">);</span>
    <span class="k">friend</span> <span class="n">IRConstInt</span> <span class="k">operator</span><span class="o">~</span><span class="p">(</span><span class="n">IRConstInt</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! Value of the integer</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">value</span><span class="p">;</span>
    <span class="c1">//! Check to know if the constant is a unsigned</span>
    <span class="c1">//! or signed value.</span>
    <span class="kt">bool</span> <span class="n">is_signed</span><span class="p">;</span>
    <span class="c1">//! byte order of the value.</span>
    <span class="n">mem_access_t</span> <span class="n">byte_order</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irmemory-implementation"><code class="language-plaintext highlighter-rouge">IRMemory</code> implementation</h6>

<p>Memory operands are specified as the memory address, an offset, a byte order and a size.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRMemory</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief IRMemory constructor this represent a memory address with accessed offset and size.
     * @param mem_address: address of the memory.
     * @param offset: offset accessed (commonly 0).
     * @param byte_order: byte order of the memory (LE, BE, ME?).
     * @param type_name: memory representation with a string.
     * @param type_size: size of the memory.
     * @return void
     */</span>
    <span class="n">IRMemory</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">mem_address</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">int32_t</span> <span class="n">offset</span><span class="p">,</span> <span class="n">mem_access_t</span> <span class="n">byte_order</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRMemory</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">get_mem_address</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">int32_t</span> <span class="n">get_offset</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irmemory_t</span> <span class="n">memory</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRMemory</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRMemory</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! accessed address</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">mem_address</span><span class="p">;</span>
    <span class="c1">//! offset of the memory accessed</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">int32_t</span> <span class="n">offset</span><span class="p">;</span>
    <span class="c1">//! byte order of the memory.</span>
    <span class="n">mem_access_t</span> <span class="n">byte_order</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irstring-implementation"><code class="language-plaintext highlighter-rouge">IRString</code> implementation</h6>

<p>Languages like C or C++, represent strings as constant strings in read-only memory, and then a pointer is used to access that data. Java-type languages use String objects. This operand is used to represent those string constant values:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRString</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRString class, this represent strings used in code.
     * @param str_value: value of that string.
     * @param type_name: some meaninful string name.
     * @param type_size: size of the type (probably here string length)
     * @return void
     */</span>
    <span class="n">IRString</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">str_value</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRString</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_str_value</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irstring_t</span> <span class="n">str</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRString</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRString</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! string value, probably nothing more will be here</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">str_value</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irclass-implementation"><code class="language-plaintext highlighter-rouge">IRClass</code> implementation</h6>

<p>For instructions like <code class="language-plaintext highlighter-rouge">IRNew</code> a class is provided as parameter to specify the object type of the created object. <code class="language-plaintext highlighter-rouge">IRClass</code> just stores the fully qualified name of the class.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRClass</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRClass, this represent the name of a class
     *        that is assigned as a type.
     * @param class_name: name of the class.
     * @param type_name: should be the same value than previous one.
     * @param type_size: should be 0.
     * @return void
     */</span>
    <span class="n">IRClass</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRClass</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_class</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irclass_t</span> <span class="n">class_</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRClass</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRClass</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! class name including path, used for instructions</span>
    <span class="c1">//! of type const-class</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="ircallee-implementation"><code class="language-plaintext highlighter-rouge">IRCallee</code> implementation</h6>

<p>In binaries created from languages like C or C++, a call specifies a register or an address where to jump, and if there are no symbols, an analysis must be done to obtain how many parameters are passed to the call. In Java-type languages, these called methods are specified by class, name and the description of the method. That description contains the return type and the parameters. MjolnIR was thought to support both, but I implemented for Dalvik, so I had all the method descriptions. <code class="language-plaintext highlighter-rouge">IRCallee</code> stores all that information:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRCallee</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Constructor of IRCallee this represent any function/method called by a caller!
     * @param addr: address of the function/method called (if available).
     * @param name: name of the function/method called (if available).
     * @param class_name: name of the class from the method called (if available).
     * @param n_of_params: number of the parameters for the function/method (if available).
     * @param description: description of the parameters from the function/method (if available).
     * @param type_name: some meaninful string name.
     * @param type_size: size of the type (probably here 0)
     * @return void
     */</span>
    <span class="n">IRCallee</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span>
                <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">,</span>
                <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">,</span>
                <span class="kt">int</span> <span class="n">n_of_params</span><span class="p">,</span>
                <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">description</span><span class="p">,</span>
                <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span>
                <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRCallee</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">get_addr</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_name</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_class_name</span><span class="p">();</span>
    <span class="kt">int</span> <span class="n">get_number_of_params</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_description</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_str</span><span class="p">();</span>
    <span class="n">mem_access_t</span> <span class="n">get_access</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">ircallee_t</span> <span class="n">callee</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRCallee</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRCallee</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! for those functions of binary formats we will mostly have the address</span>
    <span class="c1">//! only, these can be from a library, from the same binary, etc.</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">;</span>
    <span class="c1">//! name of the callee function or method, this can be resolved from the</span>
    <span class="c1">//! binary symbols if those exist or is given in case of other formats.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
    <span class="c1">//! in case it is a method, probably we will need to know class name</span>
    <span class="c1">//! for possible analysis which requires to know about a calls.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">;</span>
    <span class="c1">//! there are cases where functions/methods can have the same name but</span>
    <span class="c1">//! different parameters, you can give the number of parameters (if recognized)</span>
    <span class="c1">//! or the string with the description of the method</span>
    <span class="kt">int</span> <span class="n">n_of_params</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">description</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irfield-implementation"><code class="language-plaintext highlighter-rouge">IRField</code> implementation</h6>

<p>Java-type languages are object-oriented programming languages, and we create classes, these classes can contain methods, but also they can store fields. Fields are variables global to the objects that can be used in any method. The field can have different types, and these are expressed as an enum value:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">field_t</span>
<span class="p">{</span>
    <span class="n">CLASS_F</span><span class="p">,</span>
    <span class="n">BOOLEAN_F</span><span class="p">,</span>
    <span class="n">BYTE_F</span><span class="p">,</span>
    <span class="n">CHAR_F</span><span class="p">,</span>
    <span class="n">DOUBLE_F</span><span class="p">,</span>
    <span class="n">FLOAT_F</span><span class="p">,</span>
    <span class="n">INT_F</span><span class="p">,</span>
    <span class="n">LONG_F</span><span class="p">,</span>
    <span class="n">SHORT_F</span><span class="p">,</span>
    <span class="n">VOID_F</span><span class="p">,</span>
    <span class="n">ARRAY_F</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Then the fields in Mjolnir contain the name of the class, the name of the field, the type, and in case it is a class, the name of the class.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRField</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="cm">/**
     * @brief Construct a new IRField::IRField object
     *
     * @param class_name: class name of the field
     * @param type: type from field_t
     * @param field_name: name of the field.
     * @param type_name: some meaninful string name.
     * @param type_size: size of the type (probably here 0)
     */</span>
    <span class="n">IRField</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">,</span>
            <span class="n">field_t</span> <span class="n">type</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">field_name</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span>
            <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="n">IRField</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_class_name</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">field_name</span><span class="p">,</span>
            <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">,</span>
            <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRField</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_class_name</span><span class="p">();</span>
    <span class="n">field_t</span> <span class="n">get_type</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_type_class</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">get_name</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="n">equal</span><span class="p">(</span><span class="n">irfield_t</span> <span class="n">field</span><span class="p">);</span>
    <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">IRField</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">IRField</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="nl">private:</span>
    <span class="c1">//! Class name of the field</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_name</span><span class="p">;</span>
    <span class="c1">//! Type of the field</span>
    <span class="n">field_t</span> <span class="n">type</span><span class="p">;</span>
    <span class="c1">//! if type is class set class name</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_class</span><span class="p">;</span>
    <span class="c1">//! Field name</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">field_name</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h6 id="irfundamental-type"><code class="language-plaintext highlighter-rouge">IRFundamental</code> type</h6>

<p>In the case where we want to do data analysis and assign a type to registers or temporal registers, we can use a fundamental value. Fundamental values are provided as an enum:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">enum</span> <span class="n">fundamental_t</span>
<span class="p">{</span>
    <span class="n">F_BOOLEAN</span><span class="p">,</span>
    <span class="n">F_BYTE</span><span class="p">,</span>
    <span class="n">F_CHAR</span><span class="p">,</span>
    <span class="n">F_DOUBLE</span><span class="p">,</span>
    <span class="n">F_FLOAT</span><span class="p">,</span>
    <span class="n">F_INT</span><span class="p">,</span>
    <span class="n">F_LONG</span><span class="p">,</span>
    <span class="n">F_SHORT</span><span class="p">,</span>
    <span class="n">F_VOID</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Finally, this fundamental object only contains this enum value.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">IRFundamental</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IRType</span>
<span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">IRFundamental</span><span class="p">(</span><span class="n">fundamental_t</span> <span class="n">type</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type_name</span><span class="p">);</span>
    <span class="o">~</span><span class="n">IRFundamental</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
    <span class="n">fundamental_t</span> <span class="n">get_type</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_string</span><span class="p">();</span>
<span class="nl">private:</span>
    <span class="n">fundamental_t</span> <span class="n">type</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h4 id="mjolnir---graph-algorithms">MjolnIR - Graph Algorithms</h4>

<p>In this part of the post, we’ll dig deeper into the graph algorithms I implemented into MjolnIR. Graph algorithms can be useful to detect possible behaviors in a control-flow graph, for example, to understand from which nodes the control-flow goes from the beginning of a method to a given node. We can also use them to go over a control-flow graph in depth or in breadth order. Most of the theory from this part will be directly extracted from the book <em>Advanced Compiler Design</em> by <em>Steven S. Muchnick</em>. This is a review of an implementation, so I think it’s okay to take the theory from a well-written book.</p>

<h5 id="dominators">Dominators</h5>

<p>Having a Control-Flow Graph, we can detect things like loops in that CFG. To do that, we need to define a relation called dominance between nodes. We have that a node <code class="language-plaintext highlighter-rouge">d</code> <em>dominates</em> a node <code class="language-plaintext highlighter-rouge">i</code> (<code class="language-plaintext highlighter-rouge">d dom i</code>), if every path from the <code class="language-plaintext highlighter-rouge">entry</code> node to the node <code class="language-plaintext highlighter-rouge">i</code> goes over <code class="language-plaintext highlighter-rouge">d</code> (ALWAYS!!!)</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/d_dom_i.png">
        <img src="/assets/images/kunai_ir/d_dom_i.png" />
    </a>
    <figcaption style="text-align: center;">Graph where d dominates i</figcaption>
</figure>

<p>In the previous image we can clearly see that it doesn’t matter where control comes from to <code class="language-plaintext highlighter-rouge">i</code>, it always goes through <code class="language-plaintext highlighter-rouge">d</code>.</p>

<p><code class="language-plaintext highlighter-rouge">dom</code> is a reflexive relation (every node dominates itself), transitive (if <code class="language-plaintext highlighter-rouge">a dom b</code> and <code class="language-plaintext highlighter-rouge">b dom c</code>, then <code class="language-plaintext highlighter-rouge">a dom c</code>), and also antisymmetric (if <code class="language-plaintext highlighter-rouge">a dom b</code> and <code class="language-plaintext highlighter-rouge">b dom a</code> clearly <code class="language-plaintext highlighter-rouge">a=b</code>). Later we will see another relation called <em>immediate dominance</em>. Next we can see the pseudo-code given by <em>Muchnick</em>:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/dom_pseudocode.png">
        <img src="/assets/images/kunai_ir/dom_pseudocode.png" />
    </a>
    <figcaption style="text-align: center;">Pseudocode from the dominance algorithm</figcaption>
</figure>

<p>Now, we will analyze the implementation used in MjolnIR. First of all, let’s see how the function was:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">compute_dominators</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">);</span>
</code></pre></div></div>

<p>The function returns a map with all the blocks, and for each block, the value is the list of dominator nodes. As a parameter, the head from the CFG is given as a starting point to start calculating the dominators.</p>

<p>First of all, we will calculate all the <code class="language-plaintext highlighter-rouge">reachable_sons</code> of the head block provided by parameter, these <code class="language-plaintext highlighter-rouge">reachable_sons</code> are the nodes we can reach forward from the provided node:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">compute_dominators</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">dominators</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">nodes</span> <span class="o">=</span> <span class="n">reachable_sons</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
</code></pre></div></div>

<p>The implementation of <code class="language-plaintext highlighter-rouge">reachable_sons</code> directly calls to <code class="language-plaintext highlighter-rouge">reachable_nodes_forward</code>, as I said, are all the nodes we can reach from the provided node, to calculate this, we will go through the successors of the head node, then from the successors we will go to their successors, and so on:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Nodes</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">reachable_sons</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">reachable_nodes_forward</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">Nodes</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">reachable_nodes_forward</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Nodes</span> <span class="n">todo</span><span class="p">;</span>
    <span class="n">Nodes</span> <span class="n">reachable</span><span class="p">;</span>

    <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>

    <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">todo</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="c1">// similar to python pop.</span>
        <span class="k">auto</span> <span class="n">node_it</span> <span class="o">=</span> <span class="n">todo</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
        <span class="k">auto</span> <span class="n">node</span> <span class="o">=</span> <span class="o">*</span><span class="n">node_it</span><span class="p">;</span>
        <span class="n">todo</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">node_it</span><span class="p">);</span>

        <span class="c1">// node already in reachable</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">reachable</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">reachable</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">node</span><span class="p">)</span> <span class="o">!=</span> <span class="n">reachable</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
            <span class="k">continue</span><span class="p">;</span>

        <span class="n">reachable</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">next_node</span> <span class="o">:</span> <span class="n">get_successors</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
            <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">next_node</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">reachable</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Next, similarly to the pseudocode, we will assign to each block from <code class="language-plaintext highlighter-rouge">reachable_sons</code> that same list as dominators of that node, later we will go discarding the blocks, finally the only dominator for the head node will be the head node itself (because it is a reflexive relation). We include all those nodes in a set to apply the dominance analysis in all of them:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">node</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
    <span class="n">dominators</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="n">nodes</span><span class="p">;</span>

<span class="n">dominators</span><span class="p">[</span><span class="n">head</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">head</span><span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">todo</span><span class="p">;</span>

<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">node</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
    <span class="n">todo</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>
</code></pre></div></div>

<p>Then we have the key of the algorithm. First, we retrieve from the set the node to analyze, and we need to calculate all the predecessors of that node with a function called <code class="language-plaintext highlighter-rouge">get_predecessors</code>, for each predecessor, we have to calculate the <em>intersection</em> of their dominators (those they have in common). For example, if we have the predecessors p1, p2, p3 and p4, we will take the dominators of p1 we call it <code class="language-plaintext highlighter-rouge">dom(p1)</code>, then we will apply the intersection between <code class="language-plaintext highlighter-rouge">dom(p1)</code> and <code class="language-plaintext highlighter-rouge">dom(p2)</code>, so we will take just those elements in common, then the same with p3 <code class="language-plaintext highlighter-rouge">(dom(p1) Inter dom(p2)) Inter dom(p3)</code>, finally the same with p4. To the resulting list we will add the analyzed node itself, and in case the final list is different to the original <code class="language-plaintext highlighter-rouge">dom(node)</code>, we have the resulting dominators list from <code class="language-plaintext highlighter-rouge">node</code>, then we add all the successors from <code class="language-plaintext highlighter-rouge">node</code> and we add them to the <em>ToDo</em> list:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">todo</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">node_it</span> <span class="o">=</span> <span class="n">todo</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
    <span class="k">auto</span> <span class="n">node</span> <span class="o">=</span> <span class="o">*</span><span class="n">node_it</span><span class="p">;</span>
    <span class="n">todo</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">node_it</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">node</span> <span class="o">==</span> <span class="n">head</span><span class="p">)</span>
        <span class="c1">// do not use head for computing dominators</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="c1">// computer intersection of all predecessors'dominators</span>
    <span class="n">Nodes</span> <span class="n">new_dom</span> <span class="o">=</span> <span class="p">{};</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">pred</span> <span class="o">:</span> <span class="n">get_predecessors</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">nodes</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nodes</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">pred</span><span class="p">)</span> <span class="o">==</span> <span class="n">nodes</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="c1">// pred is not in nodes</span>
            <span class="k">continue</span><span class="p">;</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">new_dom</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
            <span class="n">new_dom</span> <span class="o">=</span> <span class="n">dominators</span><span class="p">[</span><span class="n">pred</span><span class="p">];</span>

        <span class="n">Nodes</span> <span class="n">intersect_aux</span><span class="p">;</span>

        <span class="n">std</span><span class="o">::</span><span class="n">set_intersection</span><span class="p">(</span><span class="n">new_dom</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">new_dom</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
                              <span class="n">dominators</span><span class="p">[</span><span class="n">pred</span><span class="p">].</span><span class="n">begin</span><span class="p">(),</span> <span class="n">dominators</span><span class="p">[</span><span class="n">pred</span><span class="p">].</span><span class="n">end</span><span class="p">(),</span>
                              <span class="n">std</span><span class="o">::</span><span class="n">inserter</span><span class="p">(</span><span class="n">intersect_aux</span><span class="p">,</span> <span class="n">intersect_aux</span><span class="p">.</span><span class="n">begin</span><span class="p">()));</span>

        <span class="n">new_dom</span> <span class="o">=</span> <span class="n">intersect_aux</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">new_dom</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">new_dom</span> <span class="o">==</span> <span class="n">dominators</span><span class="p">[</span><span class="n">node</span><span class="p">])</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="n">dominators</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_dom</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">succ</span> <span class="o">:</span> <span class="n">get_successors</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
        <span class="n">todo</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">succ</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And finally, our map will contain for each node, the list of dominators! Pseudocode commonly uses mathematical notation, and it is common that algorithms expressed with this notation use things like recursion, but in languages like C++ using this can make memory usage grow because each call to the same function will create a new stack, and more memory will be used.</p>

<p>We can read one example of using this algorithm by Tim Blazytko - <a href="https://www.synthesis.to/2021/03/15/control_flow_analysis.html">Introduction to Control-flow Graph Analysis</a>.</p>

<h5 id="post-dominators">Post-dominators</h5>

<p>Another concept we have is the post-dominators. We say that a node <code class="language-plaintext highlighter-rouge">p</code> <em>postdominates</em> a node <code class="language-plaintext highlighter-rouge">i</code>, written <code class="language-plaintext highlighter-rouge">p pdom i</code>, if every possible execution path from <code class="language-plaintext highlighter-rouge">i</code> to <code class="language-plaintext highlighter-rouge">exit</code> node includes <code class="language-plaintext highlighter-rouge">p</code>, this is the same that saying <code class="language-plaintext highlighter-rouge">i dom p</code> in a CFG with all the edges reversed and <code class="language-plaintext highlighter-rouge">entry</code> and <code class="language-plaintext highlighter-rouge">exit</code> interchanged. Next I post the pseudocode algorithm from the paper <a href="https://dl.acm.org/doi/pdf/10.1145/143165.143216">Generalized Dominators and Post-dominators</a>.</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/post-dom-algorithm.png">
        <img src="/assets/images/kunai_ir/post-dom-algorithm.png" />
    </a>
    <figcaption style="text-align: center;">Pseudocode from the post-dominance algorithm</figcaption>
</figure>

<p>This time the function that implements the algorithm instead of receiving as a parameter the head of the CFG, it receives a leaf from the CFG:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">compute_postdominators</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">leaf</span><span class="p">);</span>
</code></pre></div></div>

<p>And now we reverse the calls, where we called <code class="language-plaintext highlighter-rouge">reachable_sons</code> now we call <code class="language-plaintext highlighter-rouge">reachable_parents</code>, where we had a call to <code class="language-plaintext highlighter-rouge">get_predecessors</code> we will have a call to <code class="language-plaintext highlighter-rouge">get_successors</code>, and vice versa.</p>

<p>First of all from the leaf retrieve all the parents, this is a call that calls the function <code class="language-plaintext highlighter-rouge">reachable_nodes_backward</code> which retrieves the predecessors, and the predecessors of the predecessors, etc.:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Nodes</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">reachable_parents</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">leaf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">reachable_nodes_backward</span><span class="p">(</span><span class="n">leaf</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">Nodes</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">reachable_nodes_backward</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">leaf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Nodes</span> <span class="n">todo</span><span class="p">;</span>
    <span class="n">Nodes</span> <span class="n">reachable</span><span class="p">;</span>

    <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">leaf</span><span class="p">);</span>

    <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">todo</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="c1">// similar to python pop.</span>
        <span class="k">auto</span> <span class="n">node_it</span> <span class="o">=</span> <span class="n">todo</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
        <span class="k">auto</span> <span class="n">node</span> <span class="o">=</span> <span class="o">*</span><span class="n">node_it</span><span class="p">;</span>
        <span class="n">todo</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">node_it</span><span class="p">);</span>

        <span class="c1">// node already in reachable</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">reachable</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">reachable</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">node</span><span class="p">)</span> <span class="o">!=</span> <span class="n">reachable</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
            <span class="k">continue</span><span class="p">;</span>

        <span class="n">reachable</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">next_node</span> <span class="o">:</span> <span class="n">get_predecessors</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
            <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">next_node</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">reachable</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>After getting all the reachable parents, the algorithm assigns to all the nodes from the list, that list as post-dominators, assigning to the provided leaf node that same node as post-dominator.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">compute_postdominators</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">leaf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">postdominators</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">nodes</span> <span class="o">=</span> <span class="n">reachable_parents</span><span class="p">(</span><span class="n">leaf</span><span class="p">);</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">node</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
        <span class="n">postdominators</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="n">nodes</span><span class="p">;</span>

    <span class="n">postdominators</span><span class="p">[</span><span class="n">leaf</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">leaf</span><span class="p">};</span>
</code></pre></div></div>

<p>Then, as we did with dominators, we must create a <em>ToDo</em> list to go through the nodes calculating the post-dominators from each node. This time, for the analyzed node, we will retrieve the successors, and we will apply the intersection of their post-dominators, then once we have applied the intersection to all the post-dominators of the successors, we add the node itself as a post-dominator, and we add its predecessors to the <em>ToDo</em> list. And with that, we will have the post-dominators algorithm!</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Nodes</span> <span class="n">todo</span> <span class="o">=</span> <span class="n">nodes</span><span class="p">;</span>

<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">todo</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">node_it</span> <span class="o">=</span> <span class="n">todo</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
    <span class="k">auto</span> <span class="n">node</span> <span class="o">=</span> <span class="o">*</span><span class="n">node_it</span><span class="p">;</span>
    <span class="n">todo</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">node_it</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">node</span> <span class="o">==</span> <span class="n">leaf</span><span class="p">)</span>
        <span class="c1">// do not use head for computing dominators</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="c1">// computer intersection of all predecessors'dominators</span>
    <span class="n">Nodes</span> <span class="n">new_dom</span> <span class="o">=</span> <span class="p">{};</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">succ</span> <span class="o">:</span> <span class="n">get_successors</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">nodes</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nodes</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">succ</span><span class="p">)</span> <span class="o">==</span> <span class="n">nodes</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="c1">// pred is not in nodes</span>
            <span class="k">continue</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">new_dom</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
            <span class="n">new_dom</span> <span class="o">=</span> <span class="n">postdominators</span><span class="p">[</span><span class="n">succ</span><span class="p">];</span>

        <span class="n">Nodes</span> <span class="n">intersect_aux</span><span class="p">;</span>
        <span class="n">std</span><span class="o">::</span><span class="n">set_intersection</span><span class="p">(</span><span class="n">new_dom</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">new_dom</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
                              <span class="n">postdominators</span><span class="p">[</span><span class="n">succ</span><span class="p">].</span><span class="n">begin</span><span class="p">(),</span> <span class="n">postdominators</span><span class="p">[</span><span class="n">succ</span><span class="p">].</span><span class="n">end</span><span class="p">(),</span>
                              <span class="n">std</span><span class="o">::</span><span class="n">inserter</span><span class="p">(</span><span class="n">intersect_aux</span><span class="p">,</span> <span class="n">intersect_aux</span><span class="p">.</span><span class="n">begin</span><span class="p">()));</span>
        <span class="n">new_dom</span> <span class="o">=</span> <span class="n">intersect_aux</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">new_dom</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">new_dom</span> <span class="o">==</span> <span class="n">postdominators</span><span class="p">[</span><span class="n">node</span><span class="p">])</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="n">postdominators</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_dom</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">pred</span> <span class="o">:</span> <span class="n">get_predecessors</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
        <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">pred</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h5 id="immediate-dominators">Immediate Dominators</h5>

<p>Before I wrote about the definition of dominators, but we can define a subrelation called <em>immediate dominance</em> (known as <code class="language-plaintext highlighter-rouge">idom</code>) such that for a node <code class="language-plaintext highlighter-rouge">a</code> different to node <code class="language-plaintext highlighter-rouge">b</code>, <code class="language-plaintext highlighter-rouge">a idom b</code> if and only if <code class="language-plaintext highlighter-rouge">a dom b</code> and it does not exist a node <code class="language-plaintext highlighter-rouge">c</code> different to <code class="language-plaintext highlighter-rouge">a</code> and different to <code class="language-plaintext highlighter-rouge">b</code>, for which <code class="language-plaintext highlighter-rouge">a dom c</code> and <code class="language-plaintext highlighter-rouge">c dom b</code>, so a dominator of <code class="language-plaintext highlighter-rouge">b</code> such that there’s not another dominator node in the middle (for that reason immediate…). And we write it as <code class="language-plaintext highlighter-rouge">idom(b)</code>. This dominator is an immediate dominator and is clearly unique, and the relation forms a tree of the nodes of a flow-graph whose root is the entry node, whose edges are the immediate dominances, and whose paths display all the dominance relationship. I think this explanation by Muchnick is clear enough. We can see the generated tree of immediate dominators in the next image:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/immediate-dominators-tree.jpg">
        <img src="/assets/images/kunai_ir/immediate-dominators-tree.jpg" />
    </a>
    <figcaption style="text-align: center;">Tree of immediate dominators from a graph (taken from the slides "Dominators and CFGs" from University of Delaware Compiler Notes.</figcaption>
</figure>

<p>Muchnick for calculating the immediate dominators use the previously calculated dominators, we can see it in the next pseudocode:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/immediate-dominator-algorithm.png">
        <img src="/assets/images/kunai_ir/immediate-dominator-algorithm.png" />
    </a>
    <figcaption style="text-align: center;">Pseudocode of immediate dominators algorithm.</figcaption>
</figure>

<p>This time MjolnIR’s function to calculate immediate dominators, returns a map, but the map is only a pair of nodes to map one node with its immediate dominator:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">compute_immediate_dominators</span><span class="p">();</span>
</code></pre></div></div>

<p>The first thing we do for calculating the immediate dominators is calculating the dominators as we have already seen in the pseudocode:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">compute_immediate_dominators</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">tmp</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">idom</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">nodes</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">idom</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">first_node</span> <span class="o">=</span> <span class="n">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>

    <span class="c1">// compute the dominators</span>
    <span class="n">tmp</span> <span class="o">=</span> <span class="n">compute_dominators</span><span class="p">(</span><span class="n">first_node</span><span class="p">);</span>
</code></pre></div></div>

<p>Then, from the list of dominators of each node, we remove the node itself from that list:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// remove itself from dominators</span>
<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">item</span> <span class="o">:</span> <span class="n">tmp</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">rem</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">item</span><span class="p">.</span><span class="n">first</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">rem</span> <span class="o">!=</span> <span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
        <span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">rem</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The algorithm then takes a node for the analysis. From that node, we will use the dominator list of its dominators to obtain the immediate dominators. We can clearly see it with an example from Muchnick’s book, first we have a list of dominators for each node:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/idom-1.png">
        <img src="/assets/images/kunai_ir/idom-1.png" />
    </a>
    <figcaption style="text-align: center;">Tmp initialize with dominators, without the node itself.</figcaption>
</figure>

<p>Now, we go to <code class="language-plaintext highlighter-rouge">B1</code>, from <code class="language-plaintext highlighter-rouge">B1</code> from the list of dominators of <code class="language-plaintext highlighter-rouge">B1</code> (<code class="language-plaintext highlighter-rouge">{entry}</code>) we will remove the dominators from its dominators (in this case <code class="language-plaintext highlighter-rouge">entry</code>), because the list of its dominators is empty, the <code class="language-plaintext highlighter-rouge">idom(B1)</code> is <code class="language-plaintext highlighter-rouge">{entry}</code>. Now we go with <code class="language-plaintext highlighter-rouge">B2</code>, we have its list of dominators <code class="language-plaintext highlighter-rouge">{entry, B1}</code>, now we will go over the dominators list of its dominators (<code class="language-plaintext highlighter-rouge">B1</code> and <code class="language-plaintext highlighter-rouge">entry</code>) and we will remove the node that appears in those lists. The current <code class="language-plaintext highlighter-rouge">dom(B1)</code> now it is only <code class="language-plaintext highlighter-rouge">{entry}</code>, and we have that <code class="language-plaintext highlighter-rouge">dom(B2) = {entry, B1}</code>, we remove <code class="language-plaintext highlighter-rouge">{entry}</code> and we have that <code class="language-plaintext highlighter-rouge">dom(B2) = {B1}</code>, because the <code class="language-plaintext highlighter-rouge">dom(entry)</code> is empty, the algorithm is finished. We apply the same algorithm with all the next nodes. The C++ code for this is as follows:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">n</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">s</span> <span class="o">:</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">])</span>
    <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">t</span> <span class="o">:</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">])</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">t</span> <span class="o">==</span> <span class="n">s</span><span class="p">)</span>
                <span class="k">continue</span><span class="p">;</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="n">s</span><span class="p">].</span><span class="n">begin</span><span class="p">(),</span> <span class="n">tmp</span><span class="p">[</span><span class="n">s</span><span class="p">].</span><span class="n">end</span><span class="p">(),</span> <span class="n">t</span><span class="p">)</span> <span class="o">!=</span> <span class="n">tmp</span><span class="p">[</span><span class="n">s</span><span class="p">].</span><span class="n">end</span><span class="p">())</span>
            <span class="p">{</span>
                <span class="k">auto</span> <span class="n">rem</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">begin</span><span class="p">(),</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">end</span><span class="p">(),</span> <span class="n">t</span><span class="p">);</span>

                <span class="k">if</span> <span class="p">(</span><span class="n">rem</span> <span class="o">!=</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">end</span><span class="p">())</span>
                    <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">erase</span><span class="p">(</span><span class="n">rem</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally, if the <code class="language-plaintext highlighter-rouge">tmp</code> list is not empty, we have that the last node from that list of dominators will be the immediate dominator. In the example from Muchnick we have the next final list:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/idom-2.png">
        <img src="/assets/images/kunai_ir/idom-2.png" />
    </a>
    <figcaption style="text-align: center;">List of immediate dominators for each node.</figcaption>
</figure>

<p>We implement it in C++ like so:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">n</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;=</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">idom</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
    <span class="k">else</span>
        <span class="n">idom</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="nb">nullptr</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">idom</code> map contains for each node the immediate dominators.</p>

<p>We can go again to Tim Blazytko’s blog again, and see how to use immediate dominators for <a href="https://synthesis.to/2021/03/03/flattening_detection.html">Automated Detection of Control-flow Flattening</a>.</p>

<h5 id="immediate-post-dominators">Immediate Post-dominators</h5>

<p>Similarly to Immediate Dominators, we have the concept of Immediate Post-Dominators. The algorithm is basically the same but getting the post-dominators instead of the dominators, so here we can just check the algorithm with the explanation from the previous point:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">compute_immediate_postdominators</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">Nodes</span><span class="o">&gt;</span> <span class="n">tmp</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">ipdom</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">nodes</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">ipdom</span><span class="p">;</span>

    <span class="c1">// compute post dominators</span>
    <span class="k">auto</span> <span class="n">last_node</span> <span class="o">=</span> <span class="n">nodes</span><span class="p">.</span><span class="n">back</span><span class="p">();</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">compute_postdominators</span><span class="p">(</span><span class="n">last_node</span><span class="p">);</span>

    <span class="c1">// remove itself from postdominators</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">item</span> <span class="o">:</span> <span class="n">tmp</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="n">rem</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">item</span><span class="p">.</span><span class="n">first</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">rem</span> <span class="o">!=</span> <span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
            <span class="n">item</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">rem</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">n</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">s</span> <span class="o">:</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">])</span> <span class="c1">// get the post dominators</span>
        <span class="p">{</span>
            <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">t</span> <span class="o">:</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">])</span> <span class="c1">// get again the post dominators except for s</span>
            <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">t</span> <span class="o">==</span> <span class="n">s</span><span class="p">)</span>
                    <span class="k">continue</span><span class="p">;</span>

                <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="n">s</span><span class="p">].</span><span class="n">begin</span><span class="p">(),</span> <span class="n">tmp</span><span class="p">[</span><span class="n">s</span><span class="p">].</span><span class="n">end</span><span class="p">(),</span> <span class="n">t</span><span class="p">)</span> <span class="o">!=</span> <span class="n">tmp</span><span class="p">[</span><span class="n">s</span><span class="p">].</span><span class="n">end</span><span class="p">())</span>
                <span class="p">{</span>
                    <span class="k">auto</span> <span class="n">rem</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">begin</span><span class="p">(),</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">end</span><span class="p">(),</span> <span class="n">t</span><span class="p">);</span>

                    <span class="k">if</span> <span class="p">(</span><span class="n">rem</span> <span class="o">!=</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">end</span><span class="p">())</span>
                        <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">erase</span><span class="p">(</span><span class="n">rem</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">n</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;=</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">ipdom</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="n">tmp</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
        <span class="k">else</span>
            <span class="n">ipdom</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="nb">nullptr</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">ipdom</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h5 id="dominance-frontier">Dominance Frontier</h5>

<p>We can find this concept in the paper <a href="https://www.cs.utexas.edu/~pingali/CS380C/2010/papers/ssaCytron.pdf"><em>Efficiently Computing Static Single Assignment Form and the Control Dependence Graph</em></a> by Cytron et al. We have that a <em>dominance frontier</em> (commonly written as <code class="language-plaintext highlighter-rouge">DF(X)</code>) of a CFG node <code class="language-plaintext highlighter-rouge">X</code> is the set of all CFG nodes <code class="language-plaintext highlighter-rouge">Y</code> such that <code class="language-plaintext highlighter-rouge">X</code> dominates a predecessor of <code class="language-plaintext highlighter-rouge">Y</code> but does not strictly dominate <code class="language-plaintext highlighter-rouge">Y</code>. What does “Strictly dominate” mean? We can return to Muchnick, after explaining immediate dominators it says <em>“We say that d strictly dominates i, written d sdom i, if d dominates i and d is different to i”</em>. This algorithm of Dominance Frontier is commonly used to place the Phi functions (already explained in the instructions for MjolnIR). Next, the pseudocode of Dominance Frontier by Cytron et al.</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/cytron_df.png">
        <img src="/assets/images/kunai_ir/cytron_df.png" />
    </a>
    <figcaption style="text-align: center;">Pseudocode of Dominance Frontier by Cytron et al.</figcaption>
</figure>

<p>Now we will see the algorithm in MjolnIR used to obtain the dominance frontier; the algorithm is a C++ version of the one used in <code class="language-plaintext highlighter-rouge">Miasm</code>.</p>

<p>First of all, the algorithm computes the immediate dominators, with the immediate dominator tree. It will be easy to see which nodes dominate one of the analyzed node’s predecessors, and do not strictly dominate the analyzed node.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;&gt;</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">compute_dominance_frontier</span><span class="p">()</span>
<span class="p">{</span>
    <span class="cm">/*
     * Compute the immediate dominators from all the
     * nodes.
     */</span>
    <span class="k">auto</span> <span class="n">idoms</span> <span class="o">=</span> <span class="n">compute_immediate_dominators</span><span class="p">();</span>
</code></pre></div></div>

<p>Since the Dominance Frontier will be used to detect places where to write phi instructions, we will need to get the dominance frontier from the convergence nodes (those with two or more predecessors). The way we do that is checking the predecessors from the nodes from the <code class="language-plaintext highlighter-rouge">idom</code> tree:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">idom</span> <span class="o">:</span> <span class="n">idoms</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">predecessors</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">idom</span><span class="p">.</span><span class="n">first</span><span class="p">)</span> <span class="o">==</span> <span class="n">predecessors</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">||</span> <span class="n">predecessors</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="n">idom</span><span class="p">.</span><span class="n">first</span><span class="p">).</span><span class="n">size</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">continue</span><span class="p">;</span>
</code></pre></div></div>

<p>Then, we go through the predecessors from the analyzed node (<code class="language-plaintext highlighter-rouge">idom.first</code> the key from the map of immediate dominators). For each predecessor we will check if it is in the <code class="language-plaintext highlighter-rouge">idoms</code> tree. Then we will go through the <code class="language-plaintext highlighter-rouge">idom</code> tree from the current node, and from the predecessors. Inside of this loop we have to check if we are in a loop, because we are using predecessors. If we are in a loop, this loop would run forever. After that, we add in the frontier of the <code class="language-plaintext highlighter-rouge">predecessor</code> the current analyzed node, and we take the <code class="language-plaintext highlighter-rouge">idom</code> from the current predecessor as the new predecessor.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">predecessor</span> <span class="o">:</span> <span class="n">predecessors</span><span class="p">[</span><span class="n">idom</span><span class="p">.</span><span class="n">first</span><span class="p">])</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">idoms</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">predecessor</span><span class="p">)</span> <span class="o">==</span> <span class="n">idoms</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="k">while</span> <span class="p">(</span><span class="n">predecessor</span> <span class="o">!=</span> <span class="n">idom</span><span class="p">.</span><span class="n">second</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">frontier</span><span class="p">[</span><span class="n">predecessor</span><span class="p">].</span><span class="n">find</span><span class="p">(</span><span class="n">idom</span><span class="p">.</span><span class="n">first</span><span class="p">)</span> <span class="o">!=</span> <span class="n">frontier</span><span class="p">[</span><span class="n">predecessor</span><span class="p">].</span><span class="n">end</span><span class="p">())</span>
            <span class="k">break</span><span class="p">;</span>

        <span class="n">frontier</span><span class="p">[</span><span class="n">predecessor</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">idom</span><span class="p">.</span><span class="n">first</span><span class="p">);</span>

        <span class="n">predecessor</span> <span class="o">=</span> <span class="n">idoms</span><span class="p">[</span><span class="n">predecessor</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We will later use this frontier to calculate where to write the phi nodes when moving from the current IR to an SSA-form.</p>

<h5 id="depth-first-search">Depth-First Search</h5>

<p>After explaining a few complicated algorithms, we will move to something simpler. Depth-First search, and Breadth-First Search, these algorithms are useful to go through the control-flow graph using two different approaches. While in MjolnIR these two algorithms are used to retrieve the list of nodes sorted, in Muchnick’s book these are used to apply transformations before or after visiting the nodes. Four different transformations are explained:</p>

<ol>
  <li>Process_Before() to perform an action before visiting each node.</li>
  <li>Process_After() to perform an action after visiting each node.</li>
  <li>Process_Succ_Before() to perform an action before visiting each successor of a node.</li>
  <li>Process_Succ_After() to perform an action after visiting each successor of a node.</li>
</ol>

<p>In the case of Depth-First Search, the algorithm visits the descendents of a node in the graph before visiting any of its siblings that are not also descendents.</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/dfs.png">
        <img src="/assets/images/kunai_ir/dfs.png" />
    </a>
    <figcaption style="text-align: center;">Order of visiting nodes in a tree using Depth-First Search (image from wikipedia).</figcaption>
</figure>

<p>Next the algorithm by Muchnick:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/dfs-algorithm.png">
        <img src="/assets/images/kunai_ir/dfs-algorithm.png" />
    </a>
    <figcaption style="text-align: center;">Pseudocode of Depth-First Search.</figcaption>
</figure>

<p>The algorithm is easy to implement using an iterative algorithm, we create a <em>ToDo</em> list for the analysis with the head of the graph. From the <em>ToDo</em> list we will take the nodes from the back of the list, in that way we always go to the successors. Finally, we retrieve the successors, and we add it to the <em>ToDo</em> list in reverse order, so once we obtain the back from the <em>ToDo</em> list, we will retrieve the first successor.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Nodes</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">Depth_First_Search</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">todo</span><span class="p">;</span>
    <span class="n">Nodes</span> <span class="n">done</span><span class="p">;</span>

    <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>

    <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">todo</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="c1">// pop last element</span>
        <span class="k">auto</span> <span class="n">node</span> <span class="o">=</span> <span class="n">todo</span><span class="p">.</span><span class="n">back</span><span class="p">();</span>
        <span class="n">todo</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">done</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">done</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">node</span><span class="p">)</span> <span class="o">!=</span> <span class="n">done</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
            <span class="k">continue</span><span class="p">;</span>

        <span class="n">done</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>

        <span class="c1">// push the nodes in reverse order</span>
        <span class="c1">// so we go from left to right in depth</span>
        <span class="k">auto</span> <span class="n">succs</span> <span class="o">=</span> <span class="n">get_successors</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>
        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">succ</span> <span class="o">=</span> <span class="n">succs</span><span class="p">.</span><span class="n">rbegin</span><span class="p">();</span> <span class="n">succ</span> <span class="o">!=</span> <span class="n">succs</span><span class="p">.</span><span class="n">rend</span><span class="p">();</span> <span class="o">++</span><span class="n">succ</span><span class="p">)</span>
            <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="o">*</span><span class="n">succ</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">done</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h5 id="breadth-first-search">Breadth-First Search</h5>

<p>Next, we have the Breadth-First Search. In this algorithm, all nodes that are immediate descendants are processed before any of their unprocessed descendants. Next is Muchnick’s algorithm using recursion:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/bfs.png">
        <img src="/assets/images/kunai_ir/bfs.png" />
    </a>
    <figcaption style="text-align: center;">Pseudocode of Breadth-First Search.</figcaption>
</figure>

<p>And a visual representation of how visiting a tree using a breadth-first search algorithm is:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/bfs-representation.png">
        <img src="/assets/images/kunai_ir/bfs-representation.png" />
    </a>
    <figcaption style="text-align: center;">Tree representation of Breadth-First Search algorithm.</figcaption>
</figure>

<p>Now the implementation in C++, this is even simpler to the previous one, we just create a list with the head of the graph, and then retrieve the successors and add it to the list , in that way we will always go in a breadth-first order:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Nodes</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">Breadth_First_Search</span><span class="p">(</span><span class="n">irblock_t</span> <span class="n">head</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">todo</span><span class="p">;</span>
    <span class="n">Nodes</span> <span class="n">done</span><span class="p">;</span>

    <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>

    <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">todo</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="c1">// pop first element</span>
        <span class="k">auto</span> <span class="n">node</span> <span class="o">=</span> <span class="n">todo</span><span class="p">.</span><span class="n">front</span><span class="p">();</span>
        <span class="n">todo</span><span class="p">.</span><span class="n">pop_front</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">done</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">done</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">node</span><span class="p">)</span> <span class="o">!=</span> <span class="n">done</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
            <span class="k">continue</span><span class="p">;</span>

        <span class="n">done</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">succ</span> <span class="o">:</span> <span class="n">get_successors</span><span class="p">(</span><span class="n">node</span><span class="p">))</span>
            <span class="n">todo</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">succ</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">done</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h5 id="cyclomatic-complexity">Cyclomatic Complexity</h5>

<p>This metric by Thomas J. McCabe allows to know the complexity of a program, or in the case of MjolnIR, to detect the complexity of a Dalvik method using the IR. We can consult it in <a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity">wikipedia</a> for example, where we can find an equation for the complexity: <code class="language-plaintext highlighter-rouge">M = E - N + 2P</code>, where <code class="language-plaintext highlighter-rouge">M</code> is the complexity, <code class="language-plaintext highlighter-rouge">E</code> the number of edges, <code class="language-plaintext highlighter-rouge">N</code> the number of nodes in the graph and <code class="language-plaintext highlighter-rouge">P</code> the number of connected components.</p>

<p>The implementation of MjolnIR is based on the implementation from Radare2, to calculate the strongly connected components, we just count those nodes that contain a return statement:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">IRGraph</span><span class="o">::</span><span class="n">get_cyclomatic_complexity</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">cyclomatic_complexity</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">return</span> <span class="n">cyclomatic_complexity</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">auto</span> <span class="n">logger</span> <span class="o">=</span> <span class="n">LOGGER</span><span class="o">::</span><span class="n">logger</span><span class="p">();</span>

    <span class="c1">// take a copy of nodes and edges</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">nodes_aux</span> <span class="o">=</span> <span class="n">nodes</span><span class="p">;</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">edges_aux</span> <span class="o">=</span> <span class="n">edges</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">E</span> <span class="o">=</span> <span class="n">edges_aux</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
    <span class="k">auto</span> <span class="n">N</span> <span class="o">=</span> <span class="n">nodes_aux</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

    <span class="kt">size_t</span> <span class="n">P</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="c1">// Go through all the nodes to calculate those</span>
    <span class="c1">// which are exit nodes</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">node</span> <span class="o">:</span> <span class="n">nodes_aux</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="n">statements</span> <span class="o">=</span> <span class="n">node</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">();</span>
        <span class="c1">// check all instructions</span>
        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">stmnt</span> <span class="o">:</span> <span class="n">statements</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">ret_ir</span><span class="p">(</span><span class="n">stmnt</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">P</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="n">cyclomatic_complexity</span> <span class="o">=</span> <span class="n">E</span> <span class="o">-</span> <span class="n">N</span> <span class="o">+</span> <span class="n">P</span> <span class="o">*</span> <span class="mi">2</span><span class="p">;</span>

    <span class="n">logger</span><span class="o">-&gt;</span><span class="n">info</span><span class="p">(</span><span class="s">"Calculated cyclomatic complexity: {}"</span><span class="p">,</span> <span class="n">cyclomatic_complexity</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">cyclomatic_complexity</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h5 id="reaching-definition">Reaching Definition</h5>

<p>Before explaining something like <em>def-use/use-def chains</em> I need to define the concept of <em>reading definition</em>. Again, we will go to Muchnick’s book to know what is this reaching definition. First of all, a definition is an assignment of some value to a variable. We say the definition reaches a given point in a method if there is an execution path from the definition to that point such that the variable may have, at that point, the value assigned by the definition. This is, from the definition, to the selected point, there’s not a redefinition of the value. The next picture shows a very simple pseudocode of that algorithm from the next link https://www.csd.uwo.ca/~mmorenom/CS447/Lectures/CodeOptimization.html/node7.html:</p>

<figure style="text-align: center;">
    <a href="/assets/images/kunai_ir/reaching-def-alg.png">
        <img src="/assets/images/kunai_ir/reaching-def-alg.png" />
    </a>
    <figcaption style="text-align: center;">Pseudocode from Reaching definition analysis.</figcaption>
</figure>

<p>This analysis is a bit more complex, so I implemented in MjolnIR it in a whole class. First of all, the algorithm involves creating a few types to store certain data. For example, we will have <code class="language-plaintext highlighter-rouge">blockinstrtuple_t</code> that is used to store the id of a basic block, and the id of an instruction:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">blockinstrtuple_t</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span><span class="p">,</span> <span class="c1">// block id</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span>  <span class="c1">// instruction id</span>
    <span class="o">&gt;</span><span class="p">;</span>
</code></pre></div></div>

<p>This tuple of data is used for storing something I called <code class="language-plaintext highlighter-rouge">regdefinitionmap_t</code> which stores the register or temporal register or whatever is defined as an <code class="language-plaintext highlighter-rouge">IRExpr</code> and the place where it is defined:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">regdefinitionmap_t</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span>
    <span class="n">irexpr_t</span><span class="p">,</span> <span class="c1">// reg or temp reg</span>
    <span class="n">blockinstrtuple_t</span><span class="o">&gt;</span><span class="p">;</span>
</code></pre></div></div>

<p>Finally, MjolnIR’s code contains a set of <code class="language-plaintext highlighter-rouge">regdefinitionmap_t</code> called <code class="language-plaintext highlighter-rouge">regdefinitionset_t</code>, and each instruction <code class="language-plaintext highlighter-rouge">blockinstrtuple_t</code> will contain a <code class="language-plaintext highlighter-rouge">regdefinitionset_t</code> in a type called <code class="language-plaintext highlighter-rouge">reachingdeftype_t</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">reachingdeftype_t</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span>
    <span class="n">blockinstrtuple_t</span><span class="p">,</span>
    <span class="n">regdefinitionset_t</span><span class="o">&gt;</span><span class="p">;</span>
</code></pre></div></div>

<p>Next, the definition of the functions that will compute the reaching definition, the analysis involves understanding what the instructions do, since different instructions can be used to define a value.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">ReachingDefinition</span> <span class="p">{</span>
    <span class="p">...</span>
    <span class="cm">/**
     * @brief Compute the reaching definition of the IRGraph given
     *        for each line we will have a definition of where variables
     *        are defined, and this is nice, because it will be useful
     *        to calculate the def-use and use-def chains.
     *
     */</span>
    <span class="kt">void</span> <span class="n">compute</span><span class="p">();</span>
    
    <span class="cm">/**
     * @brief Analyze a block looking for definitions and updating the global
     *        reaching definitions object.
     *
     * @param block block to analyze.
     */</span>
    <span class="kt">bool</span> <span class="n">analyze_block</span><span class="p">(</span><span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">);</span>

     <span class="cm">/**
     * @brief Analyze the given instruction, checking if the instruction create
     *        a definition, in case a definition exists, update the set of definitions.
     *
     * @param block current analyzed block
     * @param instruction_id index of the instruction to analyze
     * @return true
     * @return false
     */</span>
    <span class="kt">bool</span> <span class="n">analyze_instruction</span><span class="p">(</span><span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">instruction_id</span><span class="p">);</span>
    
    <span class="cm">/**
     * @brief Check if the given instruction is an instruction where there is some
     *        kind of definition or redefinition of a register, in that case return
     *        the reference of the register, in other case use optional to return
     *        a std::nullopt value.
     *
     * @param instr
     * @return std::optional&lt;irexpr_t&amp;&gt;
     */</span>
    <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="n">is_reg_defined</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="o">&amp;</span><span class="n">instr</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The first thing we will do for computing the reaching definition on each line from the IR code will be to get the blocks in a Depth-First search order, then we will call <code class="language-plaintext highlighter-rouge">analyze_block</code> for each block. We will do this while new definitions are found:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">ReachingDefinition</span><span class="o">::</span><span class="n">compute</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">bool</span> <span class="n">change</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">dfs</span> <span class="o">=</span> <span class="n">graph</span><span class="o">-&gt;</span><span class="n">Depth_First_Search</span><span class="p">(</span><span class="n">graph</span><span class="o">-&gt;</span><span class="n">get_nodes</span><span class="p">()[</span><span class="mi">0</span><span class="p">]);</span>

    <span class="k">while</span> <span class="p">(</span><span class="n">change</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">change</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">block</span> <span class="o">:</span> <span class="n">dfs</span><span class="p">)</span>
            <span class="n">change</span> <span class="o">|=</span> <span class="n">analyze_block</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>For doing the analysis of each block, what we will do first is to generate the list of input definitions of the current block, that we will call <code class="language-plaintext highlighter-rouge">in(w)</code>, this list is created with the output definitions from the predecessors of the current block, we will call each list of the out definitions from each predecessor <code class="language-plaintext highlighter-rouge">out(p)</code>, then we will have that <code class="language-plaintext highlighter-rouge">in(w) = U out(p) for each p in predecessor(w)</code>. The list <code class="language-plaintext highlighter-rouge">out(p)</code> are the definitions in the last instruction of the block (these lists will be empty at the beginning of the execution, for that reason the algorithm runs iterations until no more changes appear). This is the implementation of <code class="language-plaintext highlighter-rouge">in(w) = U out(p) for each p in predecessor(w)</code> in C++:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">ReachingDefinition</span><span class="o">::</span><span class="n">analyze_block</span><span class="p">(</span><span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">regdefinitionset_t</span> <span class="n">predecesor_state</span><span class="p">;</span>
    <span class="kt">bool</span> <span class="n">modified</span><span class="p">;</span>

    <span class="c1">// Go through each predecessor of the current block</span>
    <span class="c1">// in(w) = U out(p) for p in pred(w)</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">pred</span> <span class="o">:</span> <span class="n">graph</span><span class="o">-&gt;</span><span class="n">get_predecessors</span><span class="p">(</span><span class="n">block</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="c1">// take the set of definitions from the last instruction of previous block</span>
        <span class="k">auto</span> <span class="o">&amp;</span><span class="n">lval_definitions</span> <span class="o">=</span> <span class="n">reaching_definitions</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">pred</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="n">pred</span><span class="o">-&gt;</span><span class="n">get_number_of_statements</span><span class="p">())];</span>

        <span class="c1">// add it to predecesor state</span>
        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">lval_definition</span> <span class="o">:</span> <span class="n">lval_definitions</span><span class="p">)</span>
            <span class="n">predecesor_state</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">lval_definition</span><span class="p">);</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>Then detect if there was a modification, that means checking if previously <code class="language-plaintext highlighter-rouge">in(w)</code> didn’t exist, or if the calculated <code class="language-plaintext highlighter-rouge">in(w)</code> is different to a previous <code class="language-plaintext highlighter-rouge">in(w)</code> from another iteration. For doing that, we need to do checking with the previously seen <code class="language-plaintext highlighter-rouge">reaching_definitions</code> variable, which contains all the reaching definition values. If no modification exists, return false:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">modified</span> <span class="o">=</span> <span class="p">(</span><span class="n">reaching_definitions</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="mi">0</span><span class="p">))</span> <span class="o">==</span> <span class="n">reaching_definitions</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="o">||</span> <span class="p">(</span><span class="n">reaching_definitions</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="mi">0</span><span class="p">)]</span> <span class="o">!=</span> <span class="n">predecesor_state</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">modified</span><span class="p">)</span>
    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</code></pre></div></div>

<p>Now, we save this new <code class="language-plaintext highlighter-rouge">in(w)</code> in the <code class="language-plaintext highlighter-rouge">reaching_definitions</code> variable:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">reaching_definitions</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="mi">0</span><span class="p">)]</span> <span class="o">=</span> <span class="n">predecesor_state</span><span class="p">;</span>
</code></pre></div></div>

<p>Now that we have <code class="language-plaintext highlighter-rouge">in(w)</code> we need to analyze each instruction looking for definitions, a definition in a new instruction, kills a definition in a previous instruction if they are defining the same value. We do it with a loop and calling <code class="language-plaintext highlighter-rouge">analyze_instruction</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_number_of_statements</span><span class="p">();</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">index</span><span class="o">++</span><span class="p">)</span>
    <span class="n">modified</span> <span class="o">|=</span> <span class="n">analyze_instruction</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span>

<span class="k">return</span> <span class="n">modified</span><span class="p">;</span>
</code></pre></div></div>

<p>And here we would have finished the analysis of the blocks. Now we can move to the analysis of the instructions.</p>

<p>First of all, we obtain the definitions that come to the current instruction, we need the next <code class="language-plaintext highlighter-rouge">defs = in(instr)</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">ReachingDefinition</span><span class="o">::</span><span class="n">analyze_instruction</span><span class="p">(</span><span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">instruction_id</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">bool</span> <span class="n">modified</span><span class="p">;</span>

    <span class="n">irstmnt_t</span> <span class="o">&amp;</span><span class="n">instr</span> <span class="o">=</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">().</span><span class="n">at</span><span class="p">(</span><span class="n">instruction_id</span><span class="p">);</span>
    <span class="c1">// defs = in(instr)</span>
    <span class="k">auto</span> <span class="n">defs</span> <span class="o">=</span> <span class="n">reaching_definitions</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="n">instruction_id</span><span class="p">)];</span>
</code></pre></div></div>

<p>Now we need to retrieve if the current instruction generates a new definition of a variable (register in this case), and in case there’s a definition we need to update the list of <code class="language-plaintext highlighter-rouge">out(instruction)</code> which are the definitions that goes out from this instruction, we can express it in the next way: <code class="language-plaintext highlighter-rouge">out(instr) =  gen(instr) U (in(instr) - kill(instr))</code>, the output generations are, the current generations joined with the generations that comes from previous instructions without taking in consideration those definitions that were killed by the current one! We will obtain if a register is defined calling <code class="language-plaintext highlighter-rouge">is_reg_defined</code>. All of this, is translated into C++ in the following way:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">reg_defined</span> <span class="o">=</span> <span class="n">is_reg_defined</span><span class="p">(</span><span class="n">instr</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="n">reg_defined</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// out(instr) =  gen(instr) U (in(instr) - kill(instr))</span>

    <span class="c1">// in(instr) - kill(instr)</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">defs</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> <span class="n">it</span> <span class="o">!=</span> <span class="n">defs</span><span class="p">.</span><span class="n">end</span><span class="p">();</span> <span class="n">it</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">map_value</span> <span class="o">=</span> <span class="o">*</span><span class="n">it</span><span class="p">;</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">map_value</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">reg_defined</span><span class="p">.</span><span class="n">value</span><span class="p">())</span> <span class="o">!=</span> <span class="n">map_value</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
            <span class="c1">// we are going to remove previous definitions</span>
            <span class="c1">// of the same registers</span>
            <span class="n">it</span> <span class="o">=</span> <span class="n">defs</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// gen(instr)</span>
    <span class="n">defs</span><span class="p">.</span><span class="n">insert</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally, to know if we have some modification, we have to compare the current <code class="language-plaintext highlighter-rouge">out(instruction)</code> with the previously stored <code class="language-plaintext highlighter-rouge">out(instruction)</code>, and in case there’s some modification we store this new <code class="language-plaintext highlighter-rouge">out(instruction)</code> (which is the same as <code class="language-plaintext highlighter-rouge">in(instruction+1)</code>), and return true!</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="c1">// old out(instr) == out(instr)?</span>
    <span class="n">modified</span> <span class="o">=</span> <span class="p">(</span><span class="n">reaching_definitions</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="n">instruction_id</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">==</span> <span class="n">reaching_definitions</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="o">||</span> <span class="n">reaching_definitions</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="n">instruction_id</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">!=</span> <span class="n">defs</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">modified</span><span class="p">)</span>
        <span class="c1">// in(instr+1) = out(instr)</span>
        <span class="n">reaching_definitions</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="n">instruction_id</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">=</span> <span class="n">defs</span><span class="p">;</span>

    <span class="k">return</span> <span class="n">modified</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And how does is the <code class="language-plaintext highlighter-rouge">is_reg_defined</code> function look? It’s just a function that checks the type of instruction, checks if a register is defined, and then returns that register:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="n">ReachingDefinition</span><span class="o">::</span><span class="n">is_reg_defined</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="o">&amp;</span><span class="n">instr</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">irexpr_t</span> <span class="n">reg</span><span class="p">;</span>
    <span class="c1">// A = B</span>
    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">assign_instr</span> <span class="o">=</span> <span class="n">assign_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">reg</span> <span class="o">=</span> <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="c1">// A = IRUnaryOp B</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">unary_instr</span> <span class="o">=</span> <span class="n">unary_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">reg</span> <span class="o">=</span> <span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="c1">// A = B IRBinaryOp C</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">bin_instr</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">reg</span> <span class="o">=</span> <span class="n">bin_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="c1">// A = load(MEM)</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">load_instr</span> <span class="o">=</span> <span class="n">load_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">reg</span> <span class="o">=</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="c1">// A = New Class</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">new_instr</span> <span class="o">=</span> <span class="n">new_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">reg</span> <span class="o">=</span> <span class="n">new_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="c1">// A = New Array</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">alloca_instr</span> <span class="o">=</span> <span class="n">alloca_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">reg</span> <span class="o">=</span> <span class="n">alloca_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="c1">// A = phi(A, A, A...)</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">phi_instr</span> <span class="o">=</span> <span class="n">phi_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">reg</span> <span class="o">=</span> <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="k">else</span>
        <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">nullopt</span><span class="p">;</span>

    <span class="k">return</span> <span class="n">reg</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In this way, we loop until no more definitions exist, and with all these algorithms we will have the definitions from the program, where the definitions were done, and until when these definitions exist.</p>

<p>For seeing a python implementation, I highly recommend going to the following code from <a href="https://github.com/cea-sec/miasm/blob/master/miasm/analysis/data_flow.py#L20">Miasm</a>, also as stated in their comment, I recommend reading the paper <em>A survey of data flow analysis techniques.</em> by <em>Kennedy, K. (1979)</em>.</p>

<h5 id="def-useuse-def-chains">Def-Use/Use-Def chains</h5>

<p>Finally, we arrive to an important concept from the analysis of IRs which are the def-use and the use-def chains. We previously defined the definitions as any point where a value is set in a variable. On the other side, we have uses, which are points in the graph where a variable with a definition is used. These two concepts are also referred as <em>Du-Chains</em> and <em>Ud-Chains</em> in Muchnick’s book. <em>Du-Chains</em> for a variable connects a definition of that variable to all the uses it may flow to, while a <em>ud-chain</em> connects a use to all the definitions that may flow to it. The complexity of this analysis is in detecting where a definition is used without being redefined, and which are the definitions connected to a usage.
Although we haven’t seen the implementation of the SSA form yet, it is useful saying that things like Def-Use and Use-Def chains are much easier to implement than in an IR without an SSA form. In SSA each variable can be defined just once, so for each variable we will have only one definition and multiple uses. If we do not use SSA, each variable can have multiple definitions.</p>

<p>For understanding how are def-use and use-def chains, we can go to the following link from the Miasm Project <a href="https://miasm.re/blog/2017/02/03/data_flow_analysis_depgraph.html#id18">use-def</a>, they perfectly explain how the values of two parameters from a call can come from two previous blocks, in that case, for variable <code class="language-plaintext highlighter-rouge">a</code> we have two definitions as well as for <code class="language-plaintext highlighter-rouge">b</code>. But those definitions have as use the <code class="language-plaintext highlighter-rouge">call(a,b)</code>. In that case, we would have the next <code class="language-plaintext highlighter-rouge">def-use/use-def chain</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>a = {def: lbl1.1, lbl2.1, use: lbl3.1}
b = {def: lbl1.2, lbl2.2, use: lbl3.1}
</code></pre></div></div>

<p>I also like the example they provide in the comment from their code which I highly recommend to read: <a href="https://github.com/cea-sec/miasm/blob/master/miasm/analysis/data_flow.py#L114">miasm def-use/use-def</a>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">"""
IR block:
    lbl0:
       0 A = 1
         B = 3
       1 B = 2
       2 A = A + B + 4

    Def use analysis:
    (lbl0, 0, A) =&gt; {(lbl0, 2, A)}
    (lbl0, 0, B) =&gt; {}
    (lbl0, 1, B) =&gt; {(lbl0, 2, A)}
    (lbl0, 2, A) =&gt; {}
"""</span>
</code></pre></div></div>

<p>Now, I will go with the implementation from MjolnIR. The implementation of the computation of def-use and use-def chains was done in the class <code class="language-plaintext highlighter-rouge">Optimizer</code> both in <code class="language-plaintext highlighter-rouge">optimizer.hpp</code> and <code class="language-plaintext highlighter-rouge">optimizer.cpp</code>. For calculating these chains we will need three parameters, one <code class="language-plaintext highlighter-rouge">IRGraph</code> containing the method to analyze and <code class="language-plaintext highlighter-rouge">reachingdefinition_t</code> a reaching definition analysis output from the previous point. The next functions will calculate these chains:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Optimizer</span> <span class="p">{</span>
    <span class="p">...</span>
    <span class="cm">/**
     * @brief Calculate the def-use and use-def chains in an IRGraph
     *        for doing that we need to accept a reaching definition
     *        with the analysis already run. All the changes will be
     *        applied directly to the instructions of the IRGraph.
     *
     * @param ir_graph graph of a function in MjolnIR to calculate its def-use, use-def chains
     * @param reachingdefinition the object with the reaching definition.
     */</span>
    <span class="kt">void</span> <span class="n">calculate_def_use_and_use_def_analysis</span><span class="p">(</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irgraph_t</span> <span class="n">ir_graph</span><span class="p">,</span>
                                                <span class="n">reachingdefinition_t</span> <span class="o">&amp;</span><span class="n">reachingdefinition</span><span class="p">);</span>
    <span class="p">...</span>               
    <span class="cm">/**
     * @brief Solve a def_use and use_def chain given an operand and a instruction
     *        here we will solve the reaching definition value and then we will cross-reference
     *        the instructions.
     *
     * @param operand
     * @param expr
     * @param reach_def_set
     * @param ir_graph
     */</span>
    <span class="kt">void</span> <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="o">&amp;</span><span class="n">operand</span><span class="p">,</span> <span class="n">irstmnt_t</span> <span class="n">expr</span><span class="p">,</span> <span class="n">regdefinitionset_t</span> <span class="o">&amp;</span><span class="n">reach_def_set</span><span class="p">,</span> <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irgraph_t</span> <span class="n">ir_graph</span><span class="p">);</span>
    <span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The first function <code class="language-plaintext highlighter-rouge">calculate_def_use_and_use_def_analysis</code> is the public function that will analyze the <code class="language-plaintext highlighter-rouge">IRGraph</code> and will do some kind of magic to collect the information. First of all we will go through the <code class="language-plaintext highlighter-rouge">IRBlock</code>s that belong to the graph, and as expected, from each block, we will go through the instructions (easy cheesy!):</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">Optimizer</span><span class="o">::</span><span class="n">calculate_def_use_and_use_def_analysis</span><span class="p">(</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irgraph_t</span> <span class="n">ir_graph</span><span class="p">,</span>
                                                       <span class="n">reachingdefinition_t</span> <span class="o">&amp;</span><span class="n">reachingdefinition</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">block</span> <span class="o">:</span> <span class="n">ir_graph</span><span class="o">-&gt;</span><span class="n">get_nodes</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="o">&amp;</span><span class="n">instructions</span> <span class="o">=</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">();</span>

        <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">_size_instr</span> <span class="o">=</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_number_of_statements</span><span class="p">(),</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">_size_instr</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
</code></pre></div></div>

<p>After this, we will retrieve one of the instructions, and we will check if that index (block index, instruction index) contains a <code class="language-plaintext highlighter-rouge">regdefinitionset_t</code> (if you do not remember it, you can check it in the previous section). With this, we know if there’s some definitions in that instruction or not:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="o">&amp;</span><span class="n">instr</span> <span class="o">=</span> <span class="n">instructions</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>

<span class="k">auto</span> <span class="n">reach_def_instr</span> <span class="o">=</span> <span class="n">reachingdefinition</span><span class="o">-&gt;</span><span class="n">get_reach_definition_point</span><span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">get_start_idx</span><span class="p">(),</span> <span class="n">i</span><span class="p">);</span>

<span class="c1">// check if there was a reach_def</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">reach_def_instr</span><span class="p">.</span><span class="n">has_value</span><span class="p">())</span>
    <span class="k">continue</span><span class="p">;</span>

<span class="k">auto</span> <span class="n">reach_def_set</span> <span class="o">=</span> <span class="n">reach_def_instr</span><span class="p">.</span><span class="n">value</span><span class="p">();</span>

<span class="c1">// check if set is empty</span>
<span class="k">if</span> <span class="p">(</span><span class="n">reach_def_set</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
    <span class="k">continue</span><span class="p">;</span>
</code></pre></div></div>

<p>The reaching definitions will tell us where a defined register value will reach (for that reason reaching, and for that reason definition, again easy cheesy). Now we will apply the analysis to the different MjolnIR’s instructions, some of them define registers, some of them use them. In any case, we need to apply the function <code class="language-plaintext highlighter-rouge">solve_def_use_use_def</code> to all the used registers (not the defined ones). Next is the code that cast the <code class="language-plaintext highlighter-rouge">IRStmnt</code> and applies different code for each instruction type:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// A = B</span>
<span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">assign_instr</span> <span class="o">=</span> <span class="n">assign_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">op</span> <span class="o">=</span> <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>
    <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">assign_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// A = phi(A1, A2, A3, ...)</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">phi_instr</span> <span class="o">=</span> <span class="n">phi_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span><span class="o">&amp;</span> <span class="n">params</span> <span class="o">=</span> <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_params</span><span class="p">();</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="n">op</span> <span class="o">:</span> <span class="n">params</span><span class="p">)</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">op</span><span class="p">.</span><span class="n">second</span><span class="p">,</span> <span class="n">phi_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// A = IRUnaryOp B</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">unary_op_instr</span> <span class="o">=</span> <span class="n">unary_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">unary_op_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">op</span> <span class="o">=</span> <span class="n">unary_op_instr</span><span class="o">-&gt;</span><span class="n">get_op</span><span class="p">();</span>

    <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">unary_op_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// A = B IRBinaryOp C</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">bin_op_instr</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">bin_op_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">op1</span> <span class="o">=</span> <span class="n">bin_op_instr</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">();</span>
    <span class="k">auto</span> <span class="n">op2</span> <span class="o">=</span> <span class="n">bin_op_instr</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">();</span>

    <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">op1</span><span class="p">,</span> <span class="n">bin_op_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
    <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">op2</span><span class="p">,</span> <span class="n">bin_op_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// CALL (A,B,C,...)</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">call_instr</span> <span class="o">=</span> <span class="n">call_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">op</span> <span class="o">:</span> <span class="n">call_instr</span><span class="o">-&gt;</span><span class="n">get_args</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">call_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="c1">// A = *B[C]</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">load_instr</span> <span class="o">=</span> <span class="n">load_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">source</span> <span class="o">=</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>
    <span class="k">auto</span> <span class="n">index</span> <span class="o">=</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_index</span><span class="p">();</span>

    <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">load_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">index</span><span class="p">)</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">load_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// *B[C] = A</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">store_instr</span> <span class="o">=</span> <span class="n">store_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">store_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">source</span> <span class="o">=</span> <span class="n">store_instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>

    <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">store_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// RET A</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">ret_instr</span> <span class="o">=</span> <span class="n">ret_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">ret_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">ret_value</span> <span class="o">=</span> <span class="n">ret_instr</span><span class="o">-&gt;</span><span class="n">get_return_value</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg_value</span> <span class="o">=</span> <span class="n">expr_ir</span><span class="p">(</span><span class="n">ret_value</span><span class="p">))</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">reg_value</span><span class="p">,</span> <span class="n">ret_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// JCC &lt;condition&gt;</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">jcc_instr</span> <span class="o">=</span> <span class="n">conditional_jump_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">jcc_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">condition</span> <span class="o">=</span> <span class="n">jcc_instr</span><span class="o">-&gt;</span><span class="n">get_condition</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg_value</span> <span class="o">=</span> <span class="n">expr_ir</span><span class="p">(</span><span class="n">condition</span><span class="p">))</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">reg_value</span><span class="p">,</span> <span class="n">jcc_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// BComp A, B</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">bcomp_instr</span> <span class="o">=</span> <span class="n">bcomp_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">bcomp_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">bcomp_instr</span><span class="o">-&gt;</span><span class="n">get_reg1</span><span class="p">())</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">bcomp_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">bcomp_instr</span><span class="o">-&gt;</span><span class="n">get_reg2</span><span class="p">())</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">bcomp_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// ZComp A, 0</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">zcomp_instr</span> <span class="o">=</span> <span class="n">zcomp_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">zcomp_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">zcomp_instr</span><span class="o">-&gt;</span><span class="n">get_reg</span><span class="p">())</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">zcomp_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// A = Alloca[REG]</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">alloca_instr</span> <span class="o">=</span> <span class="n">alloca_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">alloca_instr</span><span class="o">-&gt;</span><span class="n">invalidate_chains</span><span class="p">();</span>

    <span class="n">irstmnt_t</span> <span class="n">size</span> <span class="o">=</span> <span class="n">alloca_instr</span><span class="o">-&gt;</span><span class="n">get_size</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">irexpr_t</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
        <span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">alloca_instr</span><span class="p">,</span> <span class="n">reach_def_set</span><span class="p">,</span> <span class="n">ir_graph</span><span class="p">);</span>
    
<span class="p">}</span>
</code></pre></div></div>

<p>MjolnIR had helper instructions that applied the casts, or returned <code class="language-plaintext highlighter-rouge">nullptr</code> in case the instruction was not the checked one, allowing the use of <code class="language-plaintext highlighter-rouge">if</code> code to enter or not to the condition. Also, we have <code class="language-plaintext highlighter-rouge">register_ir</code> to know if a provided value is a register or not. One interesting thing is that we find the call to the function <code class="language-plaintext highlighter-rouge">invalidate_chains</code> from <code class="language-plaintext highlighter-rouge">IRStmnt</code> that will delete the def-use and the use-def chain for each instruction.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">IRStmnt</span><span class="o">::</span><span class="n">invalidate_chains</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">invalidate_use_def_chain</span><span class="p">();</span>
    <span class="n">invalidate_def_use_chains</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">invalidate_use_def_chain</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">use_def_chain</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">invalidate_def_use_chains</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">def_use_chains</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Let’s move to <code class="language-plaintext highlighter-rouge">solve_def_use_use_def</code>, here we got as parameters the operand, the expression with the instruction, the reaching definitions for that instruction and the graph with the whole method. What we do is pretty easy, we need to detect that the operand is in the reaching definition. If we detect it, we are detecting a use from a register, and with the reaching definition map we will detect where the value was defined. Then we will obtain the instruction where the register was defined and we do the next: in the definition instruction set a use for the defined register, in the current instruction set a definition for the used register.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">Optimizer</span><span class="o">::</span><span class="n">solve_def_use_use_def</span><span class="p">(</span><span class="n">irexpr_t</span> <span class="o">&amp;</span><span class="n">operand</span><span class="p">,</span>
                                      <span class="n">irstmnt_t</span> <span class="n">expr</span><span class="p">,</span>
                                      <span class="n">regdefinitionset_t</span> <span class="o">&amp;</span><span class="n">reach_def_set</span><span class="p">,</span>
                                      <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irgraph_t</span> <span class="n">ir_graph</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// we need to detect the operand in the reach definition</span>
    <span class="c1">// and in case we find it, we will create the def-use and</span>
    <span class="c1">// use-def chains.</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">reach_def_map</span> <span class="o">:</span> <span class="n">reach_def_set</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// look for the operand in the Reaching definition</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">reach_def_map</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">operand</span><span class="p">)</span> <span class="o">!=</span> <span class="n">reach_def_map</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
        <span class="p">{</span>
            <span class="k">auto</span> <span class="o">&amp;</span><span class="n">reach_def</span> <span class="o">=</span> <span class="n">reach_def_map</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="n">operand</span><span class="p">);</span>

            <span class="c1">// extract where the operand was defined.</span>
            <span class="k">auto</span> <span class="n">block</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">reach_def</span><span class="p">);</span>
            <span class="k">auto</span> <span class="n">instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">reach_def</span><span class="p">);</span>

            <span class="k">auto</span> <span class="n">definition_block</span> <span class="o">=</span> <span class="n">ir_graph</span><span class="o">-&gt;</span><span class="n">get_node_by_start_idx</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>

            <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">definition_block</span><span class="p">.</span><span class="n">has_value</span><span class="p">())</span>
                <span class="k">continue</span><span class="p">;</span>

            <span class="c1">// get the instruction, we will use it to cross-reference both</span>
            <span class="k">auto</span> <span class="n">definition_instr</span> <span class="o">=</span> <span class="n">definition_block</span><span class="p">.</span><span class="n">value</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">().</span><span class="n">at</span><span class="p">(</span><span class="n">instr</span><span class="p">);</span>

            <span class="c1">// set one use of a definition</span>
            <span class="n">definition_instr</span><span class="o">-&gt;</span><span class="n">add_instr_to_use_def_chain</span><span class="p">(</span><span class="n">expr</span><span class="p">);</span>

            <span class="c1">// set one definition of a use</span>
            <span class="n">expr</span><span class="o">-&gt;</span><span class="n">add_instr_to_def_use_chain</span><span class="p">(</span><span class="n">operand</span><span class="p">,</span> <span class="n">definition_instr</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Then, we will have in each instruction the uses as a list of instructions where the defined value is used. And in the use instruction, we will have for the operand a list of definition instructions. <code class="language-plaintext highlighter-rouge">IRStmnt</code> has a method for printing these chains:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">IRStmnt</span><span class="o">::</span><span class="n">print_use_def_and_def_use_chain</span><span class="p">()</span>
<span class="p">{</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Use-Def and Def-Use chain of: "</span> <span class="o">&lt;&lt;</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">to_string</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">use_def_chain</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">Use-Def chain:</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">use_def</span> <span class="o">:</span> <span class="n">use_def_chain</span><span class="p">)</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t\t</span><span class="s">"</span> <span class="o">&lt;&lt;</span> <span class="n">use_def</span><span class="o">-&gt;</span><span class="n">to_string</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">def_use_chains</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">Def-Use chains:</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">def_use</span> <span class="o">:</span> <span class="n">def_use_chains</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">auto</span> <span class="o">&amp;</span><span class="n">value</span> <span class="o">=</span> <span class="n">def_use</span><span class="p">.</span><span class="n">first</span><span class="p">;</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t\t</span><span class="s">"</span> <span class="o">&lt;&lt;</span> <span class="n">value</span><span class="o">-&gt;</span><span class="n">to_string</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">": "</span><span class="p">;</span>
            <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">def</span> <span class="o">:</span> <span class="n">def_use</span><span class="p">.</span><span class="n">second</span><span class="p">)</span>
                <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">def</span><span class="o">-&gt;</span><span class="n">to_string</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As I commented, for an SSA-form this will be simpler since only one definition exists with multiple uses. But for now, this is all!</p>

<h4 id="mjolnir---analysis">MjolnIR - Analysis</h4>

<p>Once we have seen all the graph algorithms, we can go to the usage of these algorithms. This section of the long post will have one larger subsection, and others are shorter because I couldn’t improve that part of the code in the past.</p>

<h5 id="ssa-graph-generation">SSA Graph generation</h5>

<p>As I previously said, there is a form of IR known as Static-Single Assignment Form (SSA Form). In this form, each time a variable is defined after an assignment, or after an operation that generates some result, a new variable is created, and that’s because variables can be assigned only once and used multiple times. This IR form was developed by IBM researchers in the 80s, and it became beneficial to apply optimizations in the IR. For example, an analysis as the def-use/use-def chains we previously saw, it becomes a single point of definition and then a list of uses, making this representation easy to obtain.</p>

<p>For obtaining this representation, there are algorithms that can be used to directly obtain this representation without obtaining an intermediate form of an IR, in this post a friend of mine and I explain this method used in a new version of MjolnIR: <a href="https://farena.in/compilers/mlir/ssa-mlir-algorithm/">https://farena.in/compilers/mlir/ssa-mlir-algorithm/</a>. But for the primitive version of MjolnIR I used the next <a href="https://www.cs.utexas.edu/~pingali/CS380C/2010/papers/ssaCytron.pdf"><em>Efficiently Computing Static Single Assignment Form and the Control Dependence Graph</em></a> by Cytron et al., as I previously said. This is because MjolnIR with <code class="language-plaintext highlighter-rouge">IRGraph</code> already had an intermediate form of IR that I was able to use (and also because at that moment it was the only way I knew).</p>

<p>For constructing the SSA Graph a new class called <code class="language-plaintext highlighter-rouge">IRGraphSSA</code> exists, this class receives in the constructor an <code class="language-plaintext highlighter-rouge">IRGraph</code> as parameter, with this the new graph will be generated, with this, and with all the next functions:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * @brief Obtain all kind of assignment that can generate
 *        a newer value for a variable.
 *
 * @param graph
 */</span>
<span class="kt">void</span> <span class="nf">collect_var_assign</span><span class="p">();</span>

<span class="cm">/**
 * @brief Look for a place in the dominance frontier where
 *        to write
 *
 */</span>
<span class="kt">void</span> <span class="nf">insert_phi_node</span><span class="p">();</span>

<span class="cm">/**
 * @brief Apply variable renaming to a basic block of the IRGraph
 *        here we will apply the global variables in order to translate
 *        each instruction.
 *
 * @param v basic block to translate.
 */</span>
<span class="kt">void</span> <span class="nf">search</span><span class="p">(</span><span class="k">const</span> <span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">v</span><span class="p">);</span>

<span class="cm">/**
 * @brief Translate an instruction to an SSA form this will involve
 *        parsing the instruction and checking if it contains registers
 *        to translate to a new SSA form.
 *
 * @param instr instruction to translate to an SSA form
 * @param p defined registers that we must remove later from stack.
 * @return irstmnt_t
 */</span>
<span class="n">irstmnt_t</span> <span class="nf">translate_instruction</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="o">&amp;</span><span class="n">instr</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irreg_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">);</span>

<span class="cm">/**
 * @brief Create a new register for the SSA, this will be used
 *        in the renaming algorithm, the algorithm is based in
 *        the one of the book
 *        "An Introduction to the Theory of Optimizing Compilers".
 *        This function will use both C and S.
 *
 * @param old_reg register we want to transform to SSA
 * @param p defined registers that we must remove later from stack.
 * @return irreg_t
 */</span>
<span class="n">irreg_t</span> <span class="nf">create_new_ssa_reg</span><span class="p">(</span><span class="n">irreg_t</span> <span class="n">old_reg</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irreg_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">);</span>

<span class="cm">/**
 * @brief Get the top of the S stack for a given register, in case
 *        it doesn't exist yet, call to create_new_ssa_reg function.
 * 
 * @param old_reg register we want to transform to SSA
 * @param p definedd registers that we must remove later from stack
 * @return irreg_t 
 */</span>
<span class="n">irreg_t</span> <span class="nf">get_top_or_create</span><span class="p">(</span><span class="n">irreg_t</span> <span class="n">old_reg</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irreg_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">);</span>
</code></pre></div></div>

<p>All these functions are used to do tasks like inserting phi instructions using the previously defined dominance frontier. Also, the algorithm needs to rename all the registers, adding a sub-index (e.g. from <code class="language-plaintext highlighter-rouge">r0</code> we will need <code class="language-plaintext highlighter-rouge">r0_1</code>, <code class="language-plaintext highlighter-rouge">r0_2</code>, etc) for each assignment done to the register. Let’s move to the constructor of this class.</p>

<p>The first thing we do in the constructor is copying the nodes and the edges, as well as calculating the dominance tree (calculating the immediate dominators).</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">IRGraphSSA</span><span class="p">(</span><span class="n">irgraph_t</span> <span class="o">&amp;</span><span class="n">code_graph</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">nodes</span> <span class="o">=</span> <span class="n">code_graph</span><span class="o">-&gt;</span><span class="n">get_nodes</span><span class="p">();</span>
    <span class="k">auto</span> <span class="n">edges</span> <span class="o">=</span> <span class="n">code_graph</span><span class="o">-&gt;</span><span class="n">get_edges</span><span class="p">();</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">node</span> <span class="o">:</span> <span class="n">nodes</span><span class="p">)</span>
        <span class="n">add_node</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">edge</span> <span class="o">:</span> <span class="n">edges</span><span class="p">)</span>
        <span class="n">add_edge</span><span class="p">(</span><span class="n">edge</span><span class="p">.</span><span class="n">first</span><span class="p">,</span> <span class="n">edge</span><span class="p">.</span><span class="n">second</span><span class="p">);</span>

    <span class="n">dominance_tree</span> <span class="o">=</span> <span class="n">compute_immediate_dominators</span><span class="p">();</span>
</code></pre></div></div>

<ul>
  <li><strong>collect_var_assign Analysis</strong></li>
</ul>

<p>Then the algorithm calls to <code class="language-plaintext highlighter-rouge">collect_var_assign</code>, this function simply collects for each register the blocks where a definition exists. First of all let’s see the call to that function:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">IRGraphSSA</span><span class="p">(</span><span class="n">irgraph_t</span> <span class="o">&amp;</span><span class="n">code_graph</span><span class="p">)</span>
<span class="p">{</span>
    <span class="p">...</span>
    <span class="n">collect_var_assign</span><span class="p">();</span>
    <span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And now what this function does:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">collect_var_assign</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">blocks</span> <span class="o">=</span> <span class="n">get_nodes</span><span class="p">();</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">block</span> <span class="o">:</span> <span class="n">blocks</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="o">&amp;</span><span class="n">instrs</span> <span class="o">=</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">();</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">instr</span> <span class="o">:</span> <span class="n">instrs</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="c1">// A = B</span>
            <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">assign_instr</span> <span class="o">=</span> <span class="n">assign_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">destination</span> <span class="o">=</span> <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">destination</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">// A = IRUnaryOp B</span>
            <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">unary_instr</span> <span class="o">=</span> <span class="n">unary_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">// A = B IRBinaryOp C</span>
            <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">binary_instr</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">binary_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">// A = LOAD(B[INDEX])</span>
            <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">load_instr</span> <span class="o">=</span> <span class="n">load_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">destination</span> <span class="o">=</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">destination</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">// A = New Class</span>
            <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">new_ir_instr</span> <span class="o">=</span> <span class="n">new_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">new_ir_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">// call &lt;callee&gt;(arg1, arg2, arg3...)</span>
            <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">call_instr</span> <span class="o">=</span> <span class="n">call_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">ret_val</span> <span class="o">=</span> <span class="n">call_instr</span><span class="o">-&gt;</span><span class="n">get_ret_val</span><span class="p">();</span>

                <span class="c1">// it can be void call</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">ret_val</span> <span class="o">==</span> <span class="nb">nullptr</span><span class="p">)</span>
                    <span class="k">continue</span><span class="p">;</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">ret_val</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">// STORE(A) = B</span>
            <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">store_instr</span> <span class="o">=</span> <span class="n">store_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">destination</span> <span class="o">=</span> <span class="n">store_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">destination</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="c1">// A = Alloca(B)</span>
            <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">alloca_instr</span> <span class="o">=</span> <span class="n">alloca_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">alloca_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
                <span class="n">irstmnt_t</span> <span class="n">size</span> <span class="o">=</span> <span class="n">alloca_instr</span><span class="o">-&gt;</span><span class="n">get_size</span><span class="p">();</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                <span class="p">}</span>

                <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">var_block_map</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">insert</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
                <span class="p">}</span>

                <span class="k">continue</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li><strong>insert_phi_node Analysis</strong></li>
</ul>

<p>So now, we should clearly see all the instructions that produce some register as a result. All of those registers are key for a map called <code class="language-plaintext highlighter-rouge">var_block_map</code> that will keep the blocks where the definitions exist. We will use that list right now for inserting the phi, because after calling <code class="language-plaintext highlighter-rouge">collect_var_assign</code>, the constructor calls <code class="language-plaintext highlighter-rouge">insert_phi_node</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">IRGraphSSA</span><span class="p">(</span><span class="n">irgraph_t</span> <span class="o">&amp;</span><span class="n">code_graph</span><span class="p">)</span>
<span class="p">{</span>
    <span class="p">...</span>
    <span class="n">insert_phi_node</span><span class="p">();</span>
    <span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Let’s take a look to <code class="language-plaintext highlighter-rouge">insert_phi_node</code>, the first thing the algorithm does is to calculate the <code class="language-plaintext highlighter-rouge">dominance frontier</code>, it will be used to detect if a phi node must be inserted:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">insert_phi_node</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">Nodes</span> <span class="n">work_list</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">seen</span><span class="p">;</span>

    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="p">,</span> <span class="n">irreg_t</span><span class="o">&gt;</span> <span class="n">inserted</span><span class="p">;</span>
    <span class="k">auto</span> <span class="n">dominance_frontier</span> <span class="o">=</span> <span class="n">compute_dominance_frontier</span><span class="p">();</span>
</code></pre></div></div>

<p>Now, we will loop through the <code class="language-plaintext highlighter-rouge">var_block_map</code> previously created, we will take the register from the key as the current register to analyze, and we will create a work list with all the blocks where the register is defined, this work list will be complemented with the <code class="language-plaintext highlighter-rouge">seen</code> list to avoid analyzing a block twice:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">p</span> <span class="o">:</span> <span class="n">var_block_map</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">const</span> <span class="n">irreg_t</span> <span class="o">&amp;</span><span class="n">reg</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">first</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">block</span> <span class="o">:</span> <span class="n">p</span><span class="p">.</span><span class="n">second</span><span class="p">)</span>
        <span class="n">work_list</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
</code></pre></div></div>

<p>We will retrieve the dominance frontier for each block, and for each one of those blocks in the dominance frontier we will add a phi instruction, we will add the result register where we assign the final value, but we will have to wait until the end of <code class="language-plaintext highlighter-rouge">IRGraphSSA</code> constructor to assign the parameters to that phi instruction, and to remove the phi values that are not needed (optimization of phi nodes).</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">work_list</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">block</span> <span class="o">=</span> <span class="n">work_list</span><span class="p">.</span><span class="n">front</span><span class="p">();</span>
    <span class="n">work_list</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">work_list</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span>
    <span class="n">seen</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">df_block</span> <span class="o">:</span> <span class="n">dominance_frontier</span><span class="p">[</span><span class="n">block</span><span class="p">])</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">inserted</span><span class="p">[</span><span class="n">df_block</span><span class="p">]</span> <span class="o">!=</span> <span class="n">reg</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="c1">// add phi node</span>
            <span class="n">inserted</span><span class="p">[</span><span class="n">df_block</span><span class="p">]</span> <span class="o">=</span> <span class="n">reg</span><span class="p">;</span>

            <span class="k">auto</span> <span class="n">phi_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRPhi</span><span class="o">&gt;</span><span class="p">();</span>
            <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">add_result</span><span class="p">(</span><span class="n">reg</span><span class="p">);</span>

            <span class="n">df_block</span><span class="o">-&gt;</span><span class="n">add_statement_at_beginning</span><span class="p">(</span><span class="n">phi_instr</span><span class="p">);</span>

            <span class="n">df_block</span><span class="o">-&gt;</span><span class="n">set_phi_node</span><span class="p">();</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="n">seen</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">seen</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">df_block</span><span class="p">)</span> <span class="o">==</span> <span class="n">seen</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
                <span class="c1">// finally add the block from dominance_frontier</span>
                <span class="c1">// into the worklist</span>
                <span class="n">work_list</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">df_block</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li><strong>Return to IRGraphSSA constructor</strong></li>
</ul>

<p>Finally, we will call a function called <code class="language-plaintext highlighter-rouge">search</code>, that we will later analyze, for both the nodes without predecessors (for example those from catch blocks), and the first node:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">IRGraphSSA</span><span class="p">(</span><span class="n">irgraph_t</span> <span class="o">&amp;</span><span class="n">code_graph</span><span class="p">)</span>
<span class="p">{</span>
    <span class="p">...</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">first_node</span> <span class="o">=</span> <span class="n">get_nodes</span><span class="p">()[</span><span class="mi">0</span><span class="p">];</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span> <span class="n">node</span> <span class="o">:</span> <span class="n">get_nodes</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">get_predecessors</span><span class="p">(</span><span class="n">node</span><span class="p">).</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">node</span> <span class="o">!=</span> <span class="n">first_node</span><span class="p">)</span>
            <span class="n">search</span><span class="p">(</span><span class="n">node</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">search</span><span class="p">(</span><span class="n">first_node</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li><strong>Renaming the registers</strong></li>
</ul>

<p>Now that we have the phi instructions in the dominance frontiers, we will apply renaming to the registers, and we will fill the phi instructions with registers for the parameters. Before digging deeper into the <code class="language-plaintext highlighter-rouge">search</code> function, let’s see two functions that are used for creating the new registers, these new registers are based in the number of the previous registers, but they include a new sub-index. For storing them, I used a stack, and I was able to retrieve the last generated register, or create a new one with a newer sub-index:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">irreg_t</span> <span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">get_top_or_create</span><span class="p">(</span><span class="n">irreg_t</span> <span class="n">old_reg</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irreg_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">S</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">old_reg</span><span class="p">)</span> <span class="o">!=</span> <span class="n">S</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">S</span><span class="p">[</span><span class="n">old_reg</span><span class="p">].</span><span class="n">size</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">S</span><span class="p">[</span><span class="n">old_reg</span><span class="p">].</span><span class="n">top</span><span class="p">();</span>
    <span class="k">else</span>
        <span class="k">return</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">old_reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">irreg_t</span> <span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">irreg_t</span> <span class="n">old_reg</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irreg_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">irreg_t</span> <span class="n">new_reg</span><span class="p">;</span> 

    <span class="k">if</span> <span class="p">(</span><span class="n">C</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">old_reg</span><span class="p">)</span> <span class="o">==</span> <span class="n">C</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
        <span class="n">C</span><span class="p">[</span><span class="n">old_reg</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="n">new_reg</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRReg</span><span class="o">&gt;</span><span class="p">(</span><span class="n">old_reg</span><span class="o">-&gt;</span><span class="n">get_id</span><span class="p">(),</span>
                                      <span class="n">C</span><span class="p">[</span><span class="n">old_reg</span><span class="p">],</span>
                                      <span class="n">old_reg</span><span class="o">-&gt;</span><span class="n">get_current_arch</span><span class="p">(),</span>
                                      <span class="n">old_reg</span><span class="o">-&gt;</span><span class="n">to_string</span><span class="p">()</span> <span class="o">+</span> <span class="s">"."</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">C</span><span class="p">[</span><span class="n">old_reg</span><span class="p">]),</span>
                                      <span class="n">old_reg</span><span class="o">-&gt;</span><span class="n">get_type_size</span><span class="p">());</span>

    <span class="c1">// save last index of the register</span>
    <span class="n">C</span><span class="p">[</span><span class="n">old_reg</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
    <span class="c1">// save all the references to new registers</span>
    <span class="c1">// from old one</span>
    <span class="n">S</span><span class="p">[</span><span class="n">old_reg</span><span class="p">].</span><span class="n">push</span><span class="p">(</span><span class="n">new_reg</span><span class="p">);</span>
    <span class="c1">// save the old register from the newer one</span>
    <span class="n">ssa_to_non_ssa_form</span><span class="p">[</span><span class="n">new_reg</span><span class="p">]</span> <span class="o">=</span> <span class="n">old_reg</span><span class="p">;</span>

    <span class="n">p</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">old_reg</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">new_reg</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As we can appreciate, <code class="language-plaintext highlighter-rouge">S</code> is used to store the new registers given the old one, <code class="language-plaintext highlighter-rouge">C</code> keeps for each old register, the last sub-index used, and finally we also have a map for translating from a new register to an old one (<code class="language-plaintext highlighter-rouge">ssa_to_non_ssa_form</code>). Finally, we can start with <code class="language-plaintext highlighter-rouge">search</code> function.</p>

<p>First of all, the function will go through each instruction from the block, each statement will be processed and translated to an SSA-form. In some case, like it could be some phi instructions, the translation will return null, and in that case we can annotate the instruction as an instruction to be removed. In another case, what we will have is a new instruction to be inserted in the list of statements.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">search</span><span class="p">(</span><span class="k">const</span> <span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">v</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// defined registers in the block</span>
    <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irreg_t</span><span class="o">&gt;</span> <span class="n">p</span><span class="p">;</span>
    <span class="c1">// instructions to remove</span>
    <span class="n">std</span><span class="o">::</span><span class="n">stack</span><span class="o">&lt;</span><span class="kt">size_t</span><span class="o">&gt;</span> <span class="n">to_remove</span><span class="p">;</span>

    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">statements</span> <span class="o">=</span> <span class="n">v</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">();</span>
    
    <span class="c1">// process each statement of the block</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">v_size</span> <span class="o">=</span> <span class="n">statements</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">v_size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="o">&amp;</span><span class="n">instr</span> <span class="o">=</span> <span class="n">statements</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>

        <span class="k">auto</span> <span class="n">new_instr</span> <span class="o">=</span> <span class="n">translate_instruction</span><span class="p">(</span><span class="n">instr</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
        <span class="c1">// check if the instruction have been removed</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">new_instr</span> <span class="o">==</span> <span class="nb">nullptr</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">to_remove</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
            <span class="k">continue</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">new_instr</span> <span class="o">!=</span> <span class="n">instr</span><span class="p">)</span>
            <span class="n">statements</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_instr</span><span class="p">;</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>Next, it is time to remove all the instructions from the statement list:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// remove from vector in post order</span>
<span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">to_remove</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">index</span> <span class="o">=</span> <span class="n">to_remove</span><span class="p">.</span><span class="n">top</span><span class="p">();</span>
    <span class="n">to_remove</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>

    <span class="n">statements</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">statements</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="n">index</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Then, we need to go through the phi instructions from the successors. Since we have translated the instructions, we know which are the last registers that have been created using SSA form, so if we find in a successor a phi instruction that as a result has one of the registers we have converted to SSA, it means that the Phi instruction receives as one of the parameters that new defined register (this is the trick why we also have <code class="language-plaintext highlighter-rouge">ssa_to_non_ssa_form</code>, to convert the registers to non-SSA form, and being able to discover if we can insert a parameter into phi :D). Finally, to know which position the parameter is, we see the position of the current analyzed block in the list of predecessors from the node with the phi instruction:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// process the phi statements from the successors</span>
<span class="k">auto</span> <span class="o">&amp;</span><span class="n">succs</span> <span class="o">=</span> <span class="n">get_successors</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">w</span> <span class="o">:</span> <span class="n">succs</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// if the next block does not contain</span>
    <span class="c1">// a phi node, just continue, avoid</span>
    <span class="c1">// all the other calculations</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">w</span><span class="o">-&gt;</span><span class="n">contains_phi_node</span><span class="p">())</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="c1">// extract which_pred is v for w</span>
    <span class="c1">// this will take by index which</span>
    <span class="c1">// predecessor is v from w</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">preds</span> <span class="o">=</span> <span class="n">get_predecessors</span><span class="p">(</span><span class="n">w</span><span class="p">);</span>
    <span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">find</span><span class="p">(</span><span class="n">preds</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">preds</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">v</span><span class="p">);</span>

    <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">it</span> <span class="o">!=</span> <span class="n">preds</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
        <span class="n">j</span> <span class="o">=</span> <span class="n">it</span> <span class="o">-</span> <span class="n">preds</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>

    <span class="c1">// now look for phi functions.</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">w_stmnts</span> <span class="o">=</span> <span class="n">w</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">();</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">w_stmnt</span> <span class="o">:</span> <span class="n">w_stmnts</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">phi_instr</span> <span class="o">=</span> <span class="n">phi_ir</span><span class="p">(</span><span class="n">w_stmnt</span><span class="p">))</span>
        <span class="p">{</span>
            <span class="c1">// trick to fill the parameters from the PHI function</span>
            <span class="c1">// extract the result register, and turn it to a non SSA form</span>
            <span class="c1">// if needed, then assign the register to the phi statement</span>
            <span class="c1">// as one of the parameters.</span>

            <span class="n">irreg_t</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRReg</span><span class="o">&gt;</span><span class="p">(</span><span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">());</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">reg</span><span class="o">-&gt;</span><span class="n">get_sub_id</span><span class="p">()</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
                <span class="n">reg</span> <span class="o">=</span> <span class="n">ssa_to_non_ssa_form</span><span class="p">[</span><span class="n">reg</span><span class="p">];</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">S</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">reg</span><span class="p">)</span> <span class="o">!=</span> <span class="n">S</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">S</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
                <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_params</span><span class="p">()[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="n">reg</span><span class="p">].</span><span class="n">top</span><span class="p">();</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally, the <code class="language-plaintext highlighter-rouge">search</code> function will call itself with the next block to analyze, which is the next block to analyze? The one that is strictly dominated by the current one, and for that we calculated the dominance tree. In that way, we will go through all the blocks in a correct order. Finally, the algorithm pops all the registers defined in that block, finishing the algorithm for transforming the <code class="language-plaintext highlighter-rouge">IRGraph</code> into an <code class="language-plaintext highlighter-rouge">IRGraphSSA</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="c1">// go through each child from the dominance tree</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">doms</span> <span class="o">:</span> <span class="n">dominance_tree</span><span class="p">)</span>
        <span class="c1">// check that current block strictly</span>
        <span class="c1">// dominates the next one to analyze</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">doms</span><span class="p">.</span><span class="n">second</span> <span class="o">==</span> <span class="n">v</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">auto</span> <span class="o">&amp;</span><span class="n">child</span> <span class="o">=</span> <span class="n">doms</span><span class="p">.</span><span class="n">first</span><span class="p">;</span>
            <span class="n">search</span><span class="p">(</span><span class="n">child</span><span class="p">);</span>
        <span class="p">}</span>

    <span class="c1">// now POP all the defined variables here!</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">x</span> <span class="o">:</span> <span class="n">p</span><span class="p">)</span>
        <span class="n">S</span><span class="p">[</span><span class="n">x</span><span class="p">].</span><span class="n">pop</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li><strong>Translating the instructions to SSA</strong></li>
</ul>

<p>Each instruction will need to be handled differently to be translated to an SSA form, since each instruction uses the registers differently. For example an assignment can contain two registers, one source and one destination, if both operands are registers, we need to check if a previous SSA register exists for the source, and then create a new SSA register for the destination register. Here it is the code for doing that:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// A = B</span>
<span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">assign_instr</span> <span class="o">=</span> <span class="n">assign_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">irstmnt_t</span> <span class="n">destination</span> <span class="o">=</span> <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>
    <span class="n">irstmnt_t</span> <span class="n">source</span> <span class="o">=</span> <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">source</span><span class="p">))</span>
        <span class="n">source</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">destination</span><span class="p">))</span>
        <span class="n">destination</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

    <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRAssign</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">destination</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">source</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Mostly, the translation of the instructions is: for the register operands we look for the last created register, or we create one; for the register sources, we create a new one.</p>

<p>The phi instruction is a different case, since the code from <code class="language-plaintext highlighter-rouge">search</code> already assigned the parameters from Phi instruction as SSA registers, so only the destination register is created. But if the phi instruction contains less than two parameters, it means that the phi instruction is not necessary, so we can remove it, we do that returning null as we previously saw in the <code class="language-plaintext highlighter-rouge">search</code> function:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Phi node (only the result)</span>
<span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">phi_instr</span> <span class="o">=</span> <span class="n">phi_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
        <span class="n">result</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

    <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRPhi</span><span class="o">&gt;</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">aux</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRPhi</span><span class="o">&gt;</span><span class="p">(</span><span class="n">new_instr</span><span class="p">);</span>
    <span class="n">aux</span><span class="o">-&gt;</span><span class="n">add_result</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">));</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">param</span> <span class="o">:</span> <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_params</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="n">aux</span><span class="o">-&gt;</span><span class="n">add_param</span><span class="p">(</span><span class="n">param</span><span class="p">.</span><span class="n">second</span><span class="p">,</span> <span class="n">param</span><span class="p">.</span><span class="n">first</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// not necessary a phi where we do not have</span>
    <span class="c1">// more than one parameter</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">aux</span><span class="o">-&gt;</span><span class="n">get_params</span><span class="p">().</span><span class="n">size</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">return</span> <span class="nb">nullptr</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>For finishing this part, you can find here the whole method used for translating the instructions to an SSA form:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">irstmnt_t</span> <span class="n">IRGraphSSA</span><span class="o">::</span><span class="n">translate_instruction</span><span class="p">(</span><span class="n">irstmnt_t</span> <span class="o">&amp;</span><span class="n">instr</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="n">irreg_t</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">irstmnt_t</span> <span class="n">new_instr</span> <span class="o">=</span> <span class="n">instr</span><span class="p">;</span>

    <span class="c1">// A = B</span>
    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">assign_instr</span> <span class="o">=</span> <span class="n">assign_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">destination</span> <span class="o">=</span> <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">source</span> <span class="o">=</span> <span class="n">assign_instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">source</span><span class="p">))</span>
            <span class="n">source</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">destination</span><span class="p">))</span>
            <span class="n">destination</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRAssign</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">destination</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">source</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="c1">// A = IRUnaryOp B</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">unary_instr</span> <span class="o">=</span> <span class="n">unary_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">op</span> <span class="o">=</span> <span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_op</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">op</span><span class="p">))</span>
            <span class="n">op</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_unary_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRUnaryOp</span><span class="o">::</span><span class="n">CAST_OP_T</span> <span class="o">&amp;&amp;</span> <span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_cast_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRUnaryOp</span><span class="o">::</span><span class="n">TO_CLASS</span><span class="p">)</span>
            <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRUnaryOp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">IRUnaryOp</span><span class="o">::</span><span class="n">CAST_OP_T</span><span class="p">,</span> <span class="n">IRUnaryOp</span><span class="o">::</span><span class="n">TO_CLASS</span><span class="p">,</span> <span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_class_cast</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op</span><span class="p">));</span>
        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_unary_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRUnaryOp</span><span class="o">::</span><span class="n">CAST_OP_T</span><span class="p">)</span>
            <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRUnaryOp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">IRUnaryOp</span><span class="o">::</span><span class="n">CAST_OP_T</span><span class="p">,</span> <span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_cast_type</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op</span><span class="p">));</span>
        <span class="k">else</span>
            <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRUnaryOp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">unary_instr</span><span class="o">-&gt;</span><span class="n">get_unary_op_type</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="c1">// A = B IRBinaryOp C</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">binary_instr</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">binary_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">op1</span> <span class="o">=</span> <span class="n">binary_instr</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">op2</span> <span class="o">=</span> <span class="n">binary_instr</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">op1</span><span class="p">))</span>
            <span class="n">op1</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">op2</span><span class="p">))</span>
            <span class="n">op2</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRBinOp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">binary_instr</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op1</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op2</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="c1">// A = LOAD(B[INDEX])</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">load_instr</span> <span class="o">=</span> <span class="n">load_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">destination</span> <span class="o">=</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">source</span> <span class="o">=</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">index</span> <span class="o">=</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_index</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">source</span><span class="p">))</span>
            <span class="n">source</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">index</span><span class="p">))</span>
            <span class="n">index</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">destination</span><span class="p">))</span>
            <span class="n">destination</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRLoad</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">destination</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">source</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">index</span><span class="p">),</span> <span class="n">load_instr</span><span class="o">-&gt;</span><span class="n">get_size</span><span class="p">());</span>
    <span class="p">}</span>
    <span class="c1">// A = New Class</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">new_ir_instr</span> <span class="o">=</span> <span class="n">new_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">new_ir_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRNew</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">new_ir_instr</span><span class="o">-&gt;</span><span class="n">get_source_class</span><span class="p">());</span>
    <span class="p">}</span>
    <span class="c1">// ret &lt;reg&gt;</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">ret_instr</span> <span class="o">=</span> <span class="n">ret_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">return_value</span> <span class="o">=</span> <span class="n">ret_instr</span><span class="o">-&gt;</span><span class="n">get_return_value</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">return_value</span><span class="p">))</span>
            <span class="n">return_value</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRRet</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">return_value</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="c1">// call &lt;callee&gt;(arg1, arg2, arg3...)</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">call_instr</span> <span class="o">=</span> <span class="n">call_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">irexpr_t</span><span class="o">&gt;</span> <span class="n">new_args</span><span class="p">;</span>
        <span class="k">auto</span> <span class="n">args</span> <span class="o">=</span> <span class="n">call_instr</span><span class="o">-&gt;</span><span class="n">get_args</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">ret_val</span> <span class="o">=</span> <span class="n">call_instr</span><span class="o">-&gt;</span><span class="n">get_ret_val</span><span class="p">();</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">arg</span> <span class="o">:</span> <span class="n">args</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRReg</span><span class="o">&gt;</span><span class="p">(</span><span class="n">arg</span><span class="p">);</span>
            <span class="n">new_args</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">));</span>
        <span class="p">}</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRCall</span><span class="o">&gt;</span><span class="p">(</span><span class="n">call_instr</span><span class="o">-&gt;</span><span class="n">get_callee</span><span class="p">(),</span> <span class="n">call_instr</span><span class="o">-&gt;</span><span class="n">get_call_type</span><span class="p">(),</span> <span class="n">new_args</span><span class="p">);</span>
        
        <span class="c1">// maybe a return void method</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">ret_val</span> <span class="o">!=</span> <span class="nb">nullptr</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">ret_val</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">ret_val</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
                <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRCall</span><span class="o">&gt;</span><span class="p">(</span><span class="n">new_instr</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">set_ret_val</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ret_val</span><span class="p">));</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="c1">// STORE(A) = B</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">store_instr</span> <span class="o">=</span> <span class="n">store_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">destination</span> <span class="o">=</span> <span class="n">store_instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">source</span> <span class="o">=</span> <span class="n">store_instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">index</span> <span class="o">=</span> <span class="n">store_instr</span><span class="o">-&gt;</span><span class="n">get_index</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">source</span><span class="p">))</span>
            <span class="n">source</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">index</span><span class="p">))</span>
            <span class="n">index</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">destination</span><span class="p">))</span>
            <span class="n">destination</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRStore</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">destination</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">source</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">index</span><span class="p">),</span> <span class="n">store_instr</span><span class="o">-&gt;</span><span class="n">get_size</span><span class="p">());</span>
    <span class="p">}</span>
    <span class="c1">// ZComp</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">zcomp</span> <span class="o">=</span> <span class="n">zcomp_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">op</span> <span class="o">=</span> <span class="n">zcomp</span><span class="o">-&gt;</span><span class="n">get_reg</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">op</span><span class="p">))</span>
            <span class="n">op</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRZComp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">zcomp</span><span class="o">-&gt;</span><span class="n">get_comparison</span><span class="p">(),</span> <span class="n">zcomp</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="c1">// BComp</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">bcomp</span> <span class="o">=</span> <span class="n">bcomp_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">op1</span> <span class="o">=</span> <span class="n">bcomp</span><span class="o">-&gt;</span><span class="n">get_reg1</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">op2</span> <span class="o">=</span> <span class="n">bcomp</span><span class="o">-&gt;</span><span class="n">get_reg2</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">op1</span><span class="p">))</span>
            <span class="n">op1</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">op2</span><span class="p">))</span>
            <span class="n">op2</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRBComp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">bcomp</span><span class="o">-&gt;</span><span class="n">get_comparison</span><span class="p">(),</span> <span class="n">bcomp</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op1</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op2</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="c1">// Alloca</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">alloca</span> <span class="o">=</span> <span class="n">alloca_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">alloca</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>
        <span class="n">irstmnt_t</span> <span class="n">size</span> <span class="o">=</span> <span class="n">alloca</span><span class="o">-&gt;</span><span class="n">get_size</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
            <span class="n">size</span> <span class="o">=</span> <span class="n">get_top_or_create</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRAlloca</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">alloca</span><span class="o">-&gt;</span><span class="n">get_source_type</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">size</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="c1">// Phi node (only the result)</span>
    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">phi_instr</span> <span class="o">=</span> <span class="n">phi_ir</span><span class="p">(</span><span class="n">instr</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">irstmnt_t</span> <span class="n">result</span> <span class="o">=</span> <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">();</span>

        <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">reg</span> <span class="o">=</span> <span class="n">register_ir</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">create_new_ssa_reg</span><span class="p">(</span><span class="n">reg</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>

        <span class="n">new_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRPhi</span><span class="o">&gt;</span><span class="p">();</span>

        <span class="k">auto</span> <span class="n">aux</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRPhi</span><span class="o">&gt;</span><span class="p">(</span><span class="n">new_instr</span><span class="p">);</span>
        <span class="n">aux</span><span class="o">-&gt;</span><span class="n">add_result</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">dynamic_pointer_cast</span><span class="o">&lt;</span><span class="n">IRExpr</span><span class="o">&gt;</span><span class="p">(</span><span class="n">result</span><span class="p">));</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">param</span> <span class="o">:</span> <span class="n">phi_instr</span><span class="o">-&gt;</span><span class="n">get_params</span><span class="p">())</span>
        <span class="p">{</span>
            <span class="n">aux</span><span class="o">-&gt;</span><span class="n">add_param</span><span class="p">(</span><span class="n">param</span><span class="p">.</span><span class="n">second</span><span class="p">,</span> <span class="n">param</span><span class="p">.</span><span class="n">first</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="c1">// not necessary a phi where we do not have</span>
        <span class="c1">// more than one parameter</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">aux</span><span class="o">-&gt;</span><span class="n">get_params</span><span class="p">().</span><span class="n">size</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span>
            <span class="k">return</span> <span class="nb">nullptr</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">new_instr</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h5 id="optimizer">optimizer</h5>

<p>We end the analysis part with the module I wasn’t able to fully program, the optimizer. The optimizer idea was having something like the optimization passes from LLVM, but of course, this is one of the most complex parts from the framework (even older versions from LLVM used an old version of the optimizer, and that part of LLVM was rewritten for a better version). In MjolnIR it was much more simple, so for the moment there was defined a function for optimizing one instruction from the IR (an <code class="language-plaintext highlighter-rouge">IRStmnt</code>), and for optimizing a full block (An <code class="language-plaintext highlighter-rouge">IRBlock</code> from an <code class="language-plaintext highlighter-rouge">IRGraph</code>), and they were defined in the following way:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">one_stmnt_opt_t</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">irstmnt_t</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">irstmnt_t</span> <span class="o">&amp;</span><span class="p">);</span>
<span class="k">using</span> <span class="n">one_block_opt_t</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">irblock_t</span> <span class="o">&amp;</span><span class="p">,</span> <span class="n">irgraph_t</span> <span class="o">&amp;</span><span class="p">);</span>
</code></pre></div></div>

<p>The optimizer class contained a vector to store functions from both:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">one_stmnt_opt_t</span><span class="o">&gt;</span> <span class="n">single_statement_optimization</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">one_block_opt_t</span><span class="o">&gt;</span> <span class="n">single_block_optimization</span><span class="p">;</span>
</code></pre></div></div>

<p>And methods to add them:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * @brief Add a single line optimization to the vector of optimizations
 *
 * @param opt
 */</span>
<span class="kt">void</span> <span class="nf">add_single_stmnt_pass</span><span class="p">(</span><span class="n">one_stmnt_opt_t</span> <span class="n">opt</span><span class="p">);</span>

<span class="cm">/**
 * @brief Add a single block optimization to the vector of optimizations
 * 
 * @param opt 
 */</span>
<span class="kt">void</span> <span class="nf">add_single_block_pass</span><span class="p">(</span><span class="n">one_block_opt_t</span> <span class="n">opt</span><span class="p">);</span>
</code></pre></div></div>

<p>Finally, there was a method to run the optimization pipeline:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * @brief Run all the selected optimizations.
 *
 * @param func
 */</span>
<span class="kt">void</span> <span class="nf">run_analysis</span><span class="p">(</span><span class="n">irgraph_t</span> <span class="n">func</span><span class="p">);</span>
</code></pre></div></div>

<p>First, the optimizations were run instruction by instruction through the single statement optimizers, and statements were updated accordingly in case there was an optimization. Secondly, the optimizations for blocks, as well, the blocks were updated accordingly. Finally, since the <code class="language-plaintext highlighter-rouge">optimizer</code> class contained the reaching definition, this reaching definition analysis was re-run after the optimizations.</p>

<p>At that moment, I wrote a few optimizations, and the user was able to retrieve a new default optimizer with those optimizations:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">optimizer_t</span> <span class="nf">NewDefaultOptimizer</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">optimizer</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Optimizer</span><span class="o">&gt;</span><span class="p">();</span>

    <span class="c1">// single statement optimizers</span>
    <span class="n">optimizer</span><span class="o">-&gt;</span><span class="n">add_single_stmnt_pass</span><span class="p">(</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">constant_folding</span><span class="p">);</span>

    <span class="c1">// single block optimizers</span>
    <span class="n">optimizer</span><span class="o">-&gt;</span><span class="n">add_single_block_pass</span><span class="p">(</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">nop_removal</span><span class="p">);</span>
    <span class="n">optimizer</span><span class="o">-&gt;</span><span class="n">add_single_block_pass</span><span class="p">(</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">expression_simplifier</span><span class="p">);</span>
    <span class="n">optimizer</span><span class="o">-&gt;</span><span class="n">add_single_block_pass</span><span class="p">(</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">instruction_combining</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">optimizer</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Later in the links you will be able to see how the optimizations were written, but here you have an example of <code class="language-plaintext highlighter-rouge">expression_simplifier</code> which took a block of code, and then tried to simplify mathematical expressions:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">expression_simplifier</span><span class="p">(</span><span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">,</span> <span class="n">irgraph_t</span> <span class="o">&amp;</span><span class="n">graph</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="o">&amp;</span><span class="n">stmnts</span> <span class="o">=</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irstmnt_t</span><span class="o">&gt;</span> <span class="n">new_statements</span><span class="p">;</span>

    <span class="c1">// The idea here is to create a new vector with new statements</span>
    <span class="c1">// also we will apply this optimizations until no more modifications</span>
    <span class="c1">// are applied, because we can apply simplification in cascase.</span>
    <span class="kt">bool</span> <span class="n">modified</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">modified</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// create a new state</span>
        <span class="n">modified</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
        <span class="n">new_statements</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>

        <span class="c1">// here analyze the instructions, and apply simplifications</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">stmnts_size</span> <span class="o">=</span> <span class="n">stmnts</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">stmnts_size</span><span class="p">;)</span>
        <span class="p">{</span>
            <span class="c1">// SimplifySubInst</span>
            <span class="c1">// X - (X - Y) -&gt; Y</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="p">])</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRBinOp</span><span class="o">::</span><span class="n">SUB_OP_T</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">stmnts_size</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">2</span> <span class="o">&amp;&amp;</span>
                <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRBinOp</span><span class="o">::</span><span class="n">SUB_OP_T</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">auto</span> <span class="n">first_instr</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
                <span class="k">auto</span> <span class="n">second_instr</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]);</span>

                <span class="k">if</span> <span class="p">(</span><span class="n">first_instr</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">first_instr</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">())</span> <span class="o">&amp;&amp;</span>
                    <span class="n">second_instr</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">first_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">()))</span>
                <span class="p">{</span>
                    <span class="n">irassign_t</span> <span class="n">assign_inst</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRAssign</span><span class="o">&gt;</span><span class="p">(</span><span class="n">second_instr</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">(),</span> <span class="n">second_instr</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">());</span>
                    <span class="n">new_statements</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">assign_inst</span><span class="p">);</span>
                    <span class="n">i</span> <span class="o">+=</span> <span class="mi">2</span><span class="p">;</span>
                    <span class="n">modified</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
                    <span class="k">continue</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
</code></pre></div></div>

<p>Another one, <code class="language-plaintext highlighter-rouge">instruction_combining</code> was also fun to write in order to simplify other mathematical instructions, combining operands:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">irblock_t</span><span class="o">&gt;</span> <span class="n">instruction_combining</span><span class="p">(</span><span class="n">irblock_t</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">,</span> <span class="n">irgraph_t</span> <span class="o">&amp;</span><span class="n">graph</span><span class="p">)</span>
<span class="p">{</span>
    <span class="p">...</span>
    <span class="c1">// (A | (B ^ C)) ^ ((A ^ C) ^ B)</span>
    <span class="c1">// =============================</span>
    <span class="c1">// (A &amp; (B ^ C))</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="p">])</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRBinOp</span><span class="o">::</span><span class="n">XOR_OP_T</span>
        <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">stmnts_size</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">5</span>
        <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRBinOp</span><span class="o">::</span><span class="n">OR_OP_T</span>
        <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">2</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">2</span><span class="p">])</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRBinOp</span><span class="o">::</span><span class="n">XOR_OP_T</span>
        <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">3</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">3</span><span class="p">])</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRBinOp</span><span class="o">::</span><span class="n">XOR_OP_T</span>
        <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">4</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">4</span><span class="p">])</span><span class="o">-&gt;</span><span class="n">get_bin_op_type</span><span class="p">()</span> <span class="o">==</span> <span class="n">IRBinOp</span><span class="o">::</span><span class="n">XOR_OP_T</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="n">first_xor</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="k">auto</span> <span class="n">second_or</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]);</span>
        <span class="k">auto</span> <span class="n">third_xor</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">2</span><span class="p">]);</span>
        <span class="k">auto</span> <span class="n">fourth_xor</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">3</span><span class="p">]);</span>
        <span class="k">auto</span> <span class="n">fifth_xor</span> <span class="o">=</span> <span class="n">bin_op_ir</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">4</span><span class="p">]);</span>
    
        <span class="k">auto</span> <span class="n">B</span> <span class="o">=</span> <span class="n">first_xor</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">();</span>
        <span class="k">auto</span> <span class="n">C</span> <span class="o">=</span> <span class="n">first_xor</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">();</span>
        <span class="k">auto</span> <span class="n">A</span> <span class="o">=</span> <span class="n">second_or</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">();</span>
    
        <span class="k">if</span> <span class="p">(</span>
            <span class="n">second_or</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">first_xor</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">())</span>
            <span class="o">&amp;&amp;</span> <span class="n">third_xor</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">A</span><span class="p">)</span>
            <span class="o">&amp;&amp;</span> <span class="n">third_xor</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">C</span><span class="p">)</span>
            <span class="o">&amp;&amp;</span> <span class="n">fourth_xor</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">third_xor</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">())</span>
            <span class="o">&amp;&amp;</span> <span class="n">fourth_xor</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">B</span><span class="p">)</span>
            <span class="o">&amp;&amp;</span> <span class="n">fifth_xor</span><span class="o">-&gt;</span><span class="n">get_op1</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">second_or</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">())</span>
            <span class="o">&amp;&amp;</span> <span class="n">fifth_xor</span><span class="o">-&gt;</span><span class="n">get_op2</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">equals</span><span class="p">(</span><span class="n">fourth_xor</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">())</span>
        <span class="p">)</span>
        <span class="p">{</span>
            <span class="k">auto</span> <span class="n">new_temporal</span> <span class="o">=</span> <span class="n">graph</span><span class="o">-&gt;</span><span class="n">get_last_temporal</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
            <span class="n">graph</span><span class="o">-&gt;</span><span class="n">set_last_temporal</span><span class="p">(</span><span class="n">new_temporal</span><span class="p">);</span>
            
            <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">temp_name</span> <span class="o">=</span> <span class="s">"t"</span> <span class="o">+</span> <span class="n">new_temporal</span><span class="p">;</span>
    
            <span class="k">auto</span> <span class="n">temp_reg</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRTempReg</span><span class="o">&gt;</span><span class="p">(</span><span class="n">new_temporal</span><span class="p">,</span><span class="n">temp_name</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
    
            <span class="k">auto</span> <span class="n">created_xor</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRBinOp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">IRBinOp</span><span class="o">::</span><span class="n">XOR_OP_T</span><span class="p">,</span> <span class="n">temp_reg</span><span class="p">,</span> <span class="n">B</span><span class="p">,</span><span class="n">C</span><span class="p">);</span>
            <span class="k">auto</span> <span class="n">created_and</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">IRBinOp</span><span class="o">&gt;</span><span class="p">(</span><span class="n">IRBinOp</span><span class="o">::</span><span class="n">AND_OP_T</span><span class="p">,</span> <span class="n">fifth_xor</span><span class="o">-&gt;</span><span class="n">get_result</span><span class="p">(),</span> <span class="n">temp_reg</span><span class="p">,</span> <span class="n">A</span><span class="p">);</span>
    
            <span class="n">new_statements</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">created_xor</span><span class="p">);</span>
            <span class="n">new_statements</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">created_and</span><span class="p">);</span>
            <span class="n">i</span> <span class="o">+=</span> <span class="mi">5</span><span class="p">;</span>
            <span class="n">modified</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
            <span class="k">continue</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="c1">// if the instruction has not been optimized,</span>
    <span class="c1">// means it is not an interesting expression</span>
    <span class="c1">// then push it and go ahead.</span>
    <span class="n">new_statements</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">stmnts</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
    <span class="n">i</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>I agree that the method wasn’t good since you had to specifically match each operand with each side of the instruction. In future versions the idea was to improve the optimizer to allow better rules, but finally, the project changed.</p>

<h4 id="mjolnir---dalvik-bytecode-lifting">MjolnIR - Dalvik Bytecode Lifting</h4>

<p>We reach the last section, which covers the lifting process that I will try to summarize to make this last part of the blog simple.</p>

<p>The lifter was able to lift the disassembled instructions from Kunai, the lifter was able to lift one single instruction to add it to a block, a block to add it to an <code class="language-plaintext highlighter-rouge">IRGraph</code>, and the main method <code class="language-plaintext highlighter-rouge">lift_android_method</code> received two Kunai objects in order to provide a full lifted Method in an <code class="language-plaintext highlighter-rouge">IRGraph</code> object.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irgraph_t</span> <span class="nf">lift_android_method</span><span class="p">(</span><span class="n">DEX</span><span class="o">::</span><span class="n">MethodAnalysis</span><span class="o">*</span> <span class="n">method_analysis</span><span class="p">,</span> <span class="n">DEX</span><span class="o">::</span><span class="n">Analysis</span><span class="o">*</span> <span class="n">android_analysis</span><span class="p">);</span>
<span class="kt">bool</span> <span class="nf">lift_android_basic_block</span><span class="p">(</span><span class="n">DEX</span><span class="o">::</span><span class="n">DVMBasicBlock</span><span class="o">*</span> <span class="n">basic_block</span><span class="p">,</span> <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irblock_t</span><span class="o">&amp;</span> <span class="n">bb</span><span class="p">);</span>
<span class="kt">bool</span> <span class="nf">lift_android_instruction</span><span class="p">(</span><span class="n">DEX</span><span class="o">::</span><span class="n">Instruction</span><span class="o">*</span> <span class="n">instruction</span><span class="p">,</span> <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irblock_t</span><span class="o">&amp;</span> <span class="n">bb</span><span class="p">);</span>
</code></pre></div></div>

<p>The process of lifting was just going block by block, lifting it, and for each block, instruction by instruction. Once all the instructions were lifted, the control-flow was created between blocks. Jump analysis and a fallthrough analysis were done to correctly detect the targets from the jumps, but also to correctly detect the fallthrough blocks. This is the function used to lift each Android method:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irgraph_t</span> <span class="n">LifterAndroid</span><span class="o">::</span><span class="n">lift_android_method</span><span class="p">(</span><span class="n">DEX</span><span class="o">::</span><span class="n">MethodAnalysis</span><span class="o">*</span> <span class="n">method_analysis</span><span class="p">,</span> <span class="n">DEX</span><span class="o">::</span><span class="n">Analysis</span><span class="o">*</span> <span class="n">android_analysis</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="o">&amp;</span> <span class="n">bbs</span> <span class="o">=</span> <span class="n">method_analysis</span><span class="o">-&gt;</span><span class="n">get_basic_blocks</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_basic_blocks</span><span class="p">();</span>
    <span class="kt">size_t</span> <span class="n">n_bbs</span> <span class="o">=</span> <span class="n">bbs</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
    <span class="c1">// set android_analysis</span>
    <span class="k">this</span><span class="o">-&gt;</span><span class="n">android_analysis</span> <span class="o">=</span> <span class="n">android_analysis</span><span class="p">;</span>
    <span class="c1">// graph returnedd by</span>
    <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irgraph_t</span> <span class="n">method_graph</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">IRGraph</span><span class="o">&gt;</span><span class="p">();</span>

    <span class="c1">// first of all lift all the blocks</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">bb</span> <span class="o">:</span> <span class="n">bbs</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irblock_t</span> <span class="n">lifted_bb</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">IRBlock</span><span class="o">&gt;</span><span class="p">();</span>

        <span class="k">this</span><span class="o">-&gt;</span><span class="n">lift_android_basic_block</span><span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="n">get</span><span class="p">(),</span> <span class="n">lifted_bb</span><span class="p">);</span>

        <span class="n">lifted_blocks</span><span class="p">[</span><span class="n">bb</span><span class="p">.</span><span class="n">get</span><span class="p">()]</span> <span class="o">=</span> <span class="n">lifted_bb</span><span class="p">;</span>

        <span class="n">method_graph</span><span class="o">-&gt;</span><span class="n">add_node</span><span class="p">(</span><span class="n">lifted_bb</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Create Control Flow Graph using the children nodes</span>
    <span class="c1">// from the method blocks.</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">bb</span> <span class="o">:</span> <span class="n">bbs</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="o">&amp;</span> <span class="n">next_bbs</span> <span class="o">=</span> <span class="n">bb</span><span class="o">-&gt;</span><span class="n">get_next</span><span class="p">();</span>

        <span class="k">auto</span> <span class="n">current_bb</span> <span class="o">=</span> <span class="n">lifted_blocks</span><span class="p">[</span><span class="n">bb</span><span class="p">.</span><span class="n">get</span><span class="p">()];</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">next_bb</span> <span class="o">:</span> <span class="n">next_bbs</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">auto</span> <span class="n">block</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">next_bb</span><span class="p">).</span><span class="n">get</span><span class="p">();</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">lifted_blocks</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">block</span><span class="p">)</span> <span class="o">==</span> <span class="n">lifted_blocks</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
                <span class="k">continue</span><span class="p">;</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">lifted_blocks</span><span class="p">[</span><span class="n">block</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">get_number_of_statements</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
                <span class="k">continue</span><span class="p">;</span>

            <span class="k">auto</span> <span class="n">last_instr</span> <span class="o">=</span> <span class="n">lifted_blocks</span><span class="p">[</span><span class="n">block</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">get_statements</span><span class="p">().</span><span class="n">back</span><span class="p">();</span>

            <span class="c1">// unsigned jumps are fixed later, they only have to point</span>
            <span class="c1">// to where jump targets</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">last_instr</span><span class="o">-&gt;</span><span class="n">get_op_type</span><span class="p">()</span> <span class="o">!=</span> <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">IRStmnt</span><span class="o">::</span><span class="n">UJMP_OP_T</span><span class="p">)</span>
                <span class="n">method_graph</span><span class="o">-&gt;</span><span class="n">add_edge</span><span class="p">(</span><span class="n">current_bb</span><span class="p">,</span> <span class="n">lifted_blocks</span><span class="p">[</span><span class="n">block</span><span class="p">]);</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">this</span><span class="o">-&gt;</span><span class="n">jump_target_analysis</span><span class="p">(</span><span class="n">bbs</span><span class="p">,</span> <span class="n">method_graph</span><span class="p">);</span>
    <span class="n">optimizer</span><span class="o">-&gt;</span><span class="n">fallthrough_target_analysis</span><span class="p">(</span><span class="n">method_graph</span><span class="p">);</span>


    <span class="n">method_graph</span><span class="o">-&gt;</span><span class="n">set_last_temporal</span><span class="p">(</span><span class="n">temp_reg_id</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
    <span class="c1">// clean android_analysis</span>
    <span class="k">this</span><span class="o">-&gt;</span><span class="n">android_analysis</span> <span class="o">=</span> <span class="nb">nullptr</span><span class="p">;</span>

    <span class="k">return</span> <span class="n">method_graph</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The translation of every instruction means understanding the semantic of each instruction, and creating an IR instruction that fits that semantic. The <code class="language-plaintext highlighter-rouge">lift_android_instruction</code> function was a veeeery long function with a veeeery long switch statement that detected the opcode of the instruction, and depending on the opcode, the functionality of the instruction was emulated with an IR instruction. A very simple example, the move instruction:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">case</span> <span class="n">DEX</span><span class="o">::</span><span class="n">DVMTypes</span><span class="o">::</span><span class="n">Opcode</span><span class="o">::</span><span class="n">OP_MOVE</span><span class="p">:</span>
<span class="k">case</span> <span class="n">DEX</span><span class="o">::</span><span class="n">DVMTypes</span><span class="o">::</span><span class="n">Opcode</span><span class="o">::</span><span class="n">OP_MOVE_WIDE</span><span class="p">:</span>
<span class="k">case</span> <span class="n">DEX</span><span class="o">::</span><span class="n">DVMTypes</span><span class="o">::</span><span class="n">Opcode</span><span class="o">::</span><span class="n">OP_MOVE_OBJECT</span><span class="p">:</span>
<span class="p">{</span>
    <span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irstmnt_t</span> <span class="n">assignment_instr</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">instr</span> <span class="o">=</span> <span class="k">reinterpret_cast</span><span class="o">&lt;</span><span class="n">DEX</span><span class="o">::</span><span class="n">Instruction12x</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">instruction</span><span class="p">);</span>
    <span class="k">auto</span> <span class="n">dest</span> <span class="o">=</span> <span class="n">instr</span><span class="o">-&gt;</span><span class="n">get_destination</span><span class="p">();</span>
    <span class="k">auto</span> <span class="n">src</span> <span class="o">=</span> <span class="n">instr</span><span class="o">-&gt;</span><span class="n">get_source</span><span class="p">();</span>

    <span class="k">auto</span> <span class="n">dest_reg</span> <span class="o">=</span> <span class="n">make_android_register</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span>
    <span class="k">auto</span> <span class="n">src_reg</span> <span class="o">=</span> <span class="n">make_android_register</span><span class="p">(</span><span class="n">src</span><span class="p">);</span>

    <span class="n">assignment_instr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">IRAssign</span><span class="o">&gt;</span><span class="p">(</span><span class="n">dest_reg</span><span class="p">,</span> <span class="n">src_reg</span><span class="p">);</span>

    <span class="n">bb</span><span class="o">-&gt;</span><span class="n">append_statement_to_block</span><span class="p">(</span><span class="n">assignment_instr</span><span class="p">);</span>

    <span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The design of a very long switch wasn’t good at all I think, so in newer versions, this long switch was replaced by an <code class="language-plaintext highlighter-rouge">unordered_map</code> and function pointers, these functions created through a template, and from the template different functions were specialized depending on the opcode or the type of the instruction.</p>

<p>Together with the lifter for the instructions, I created different helper functions to create data types like registers, temporal registers, strings, classes, fields, etc:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irreg_t</span> <span class="nf">make_android_register</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">reg_id</span><span class="p">);</span>

<span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irtempreg_t</span> <span class="nf">make_temporal_register</span><span class="p">();</span>

<span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irtype_t</span> <span class="nf">make_none_type</span><span class="p">();</span>

<span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irconstint_t</span> <span class="nf">make_int</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint64_t</span> <span class="n">value</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">is_signed</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">type_size</span><span class="p">);</span>

<span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irstring_t</span> <span class="nf">make_str</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">value</span><span class="p">);</span>

<span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irclass_t</span> <span class="nf">make_class</span><span class="p">(</span><span class="n">DEX</span><span class="o">::</span><span class="n">Class</span><span class="o">*</span> <span class="n">value</span><span class="p">);</span>

<span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irfundamental_t</span> <span class="nf">make_fundamental</span><span class="p">(</span><span class="n">DEX</span><span class="o">::</span><span class="n">Fundamental</span><span class="o">*</span> <span class="n">value</span><span class="p">);</span>

<span class="n">MJOLNIR</span><span class="o">::</span><span class="n">irfield_t</span> <span class="nf">make_field</span><span class="p">(</span><span class="n">DEX</span><span class="o">::</span><span class="n">FieldID</span><span class="o">*</span> <span class="n">field</span><span class="p">);</span>
</code></pre></div></div>

<h2 id="links">Links</h2>

<p>Next, I will paste the links of the code where you can read the whole sources for all I have talked about in the post.</p>

<ul>
  <li>Headers
    <ul>
      <li>IRGraph: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/include/KUNAI/mjolnIR/ir_graph.hpp</li>
      <li>All the classes for defining the instructions of MjolnIR: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/include/KUNAI/mjolnIR/ir_grammar.hpp</li>
      <li>All the analysis classes, the graph analyses, the optimizer, reaching definition, etc: https://github.com/Fare9/KUNAI-static-analyzer/tree/main/old/src/include/KUNAI/mjolnIR/Analysis</li>
      <li>The definitions from the lifter: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/include/KUNAI/mjolnIR/Lifters/lifter_android.hpp</li>
    </ul>
  </li>
  <li>Sources
    <ul>
      <li>Code from <code class="language-plaintext highlighter-rouge">IRBlock</code>s: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/mjolnIR/ir_blocks.cpp</li>
      <li>Code from <code class="language-plaintext highlighter-rouge">IRExpr</code>s: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/mjolnIR/ir_expr.cpp</li>
      <li>Code from <code class="language-plaintext highlighter-rouge">IRGraph</code>: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/mjolnIR/ir_graph.cpp</li>
      <li>Code from <code class="language-plaintext highlighter-rouge">IRStmnt</code>s: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/mjolnIR/ir_stmnt.cpp</li>
      <li>Code from <code class="language-plaintext highlighter-rouge">IRType</code>s: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/mjolnIR/ir_type.cpp</li>
      <li>Some utilities to work with the IR: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/mjolnIR/ir_utils.cpp</li>
      <li>All the analysis code: https://github.com/Fare9/KUNAI-static-analyzer/tree/main/old/src/mjolnIR/Analysis</li>
      <li>The code from the lifter: https://github.com/Fare9/KUNAI-static-analyzer/blob/main/old/src/mjolnIR/Lifters/lifter_android.cpp</li>
    </ul>
  </li>
</ul>

<h2 id="last-words">Last Words</h2>

<p>So… Here we are my old friend… This is the end of this long post. And maybe you jumped here directly from the beginning… But I really hope this post was useful for you, or for your team, or for your PhD thesis, master thesis or even undergrad thesis.</p>

<p>I wrote Kunai, mostly by my own, with learning purposes, even if the code grew enough to become part of my PhD thesis, but I was just chasing knowledge. I was able to improve my knowledge about the Android Dalvik file format, in programming with C++, in writing static binary analysis tools… I learned a lot. And this knowledge was pretty useful to get my current job. And now I wanted to give this knowledge to everyone else.</p>

<p>I think here is the place where I can say thank you to some people, so… Special thanks to Rob who has helped me a lot during my beginnings in Quarkslab, Matteo who always gave me his opinion about the implemented analyses, to Juan, Antonio, Angela (who also added her small contribution to the project), Qiqi (who was with me when I published this version of Kunai: Japanese version), to all my colleagues from Quarkslab, and my friends from Lega Kai. Probably I forget many other people, but specially thanks to you for reading until here.</p>

<figure>
<a href="/assets/images/hacklu-ollvm/seeu.jpeg"><img src="/assets/images/hacklu-ollvm/seeu.jpeg" /></a>
</figure>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Compilers" /><category term="Programming" /><category term="C++" /><category term="IR" /><category term="Android" /><category term="Dalvik" /><category term="Binary Analysis" /><summary type="html"><![CDATA[The following post will talk about the design of the first version of the Intermediate Representation of Kunai, the design decisions and how it was implemented.]]></summary></entry><entry><title type="html">Notes about ELF File Format</title><link href="https://fare9.github.io/reverse%20engineering/linux/elf-notes/" rel="alternate" type="text/html" title="Notes about ELF File Format" /><published>2024-06-16T00:00:00+00:00</published><updated>2024-06-16T14:52:00+00:00</updated><id>https://fare9.github.io/reverse%20engineering/linux/elf-notes</id><content type="html" xml:base="https://fare9.github.io/reverse%20engineering/linux/elf-notes/"><![CDATA[<h1 id="elf-file">ELF File</h1>

<p>Three main types of ELF files:</p>

<ul>
  <li><em>relocatable file</em> holds code and data suitable for linking with other object files, to create an executable or shared object.</li>
  <li><em>executable file</em> program suitable for execution.</li>
  <li><em>Shared object file</em> code and data suitable for linking in two contexts. Link editor may process it with other relocatable and shared object files to create another object file. Second, dynamic linker combines it with executable file and other shared objects to create process image.</li>
</ul>

<h2 id="file-format">File Format</h2>

<p>For convenience and efficiency, object file format provides different views depending on environment:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    Linking View                 Execution View

+------------------+          +------------------+
|                  |          |                  |
|     ELF Header   |          |     ELF Header   |
|                  |          |                  |
+------------------+          +------------------+
|  Program Header  |          |  Program Header  |
|  Table (optional)|          |  Table           |
|                  |          |                  |
+------------------+          +------------------+
|                  |          |                  |
|     Section 1    |          |                  |
|                  |          |    Segment 1     |
+------------------+          |                  |
|       ...        |          |                  |
+------------------+          +------------------+
|                  |          |                  |
|     Section n    |          |                  |
|                  |          |    Segment 2     |
+------------------+          |                  |
|       ...        |          |                  |
+------------------+          +------------------+
|       ...        |          |      ...         |
+------------------+          +------------------+
|  Section Header  |          |  Section Header  |
|  Table           |          |  Table (optional)|
|                  |          |                  |
+------------------+          +------------------+
</code></pre></div></div>

<p><em>Elf header</em> is at the beginning used as a “road map” describing file’s organization. <em>Sections</em> are the bulk of object file information for linking view: instructions, data, symbol table, relocation information, and so on.</p>

<p>A <em>program header table</em> tells system how to create a process image. So files that will be executed needs from a program header table; relocatable files do not need one (not intended to be executed). A <em>section header table</em> contains information describing file’s sections. Every section has an entry; each entry gives information (section name, size, etc). Files used during linking must have a section header table.</p>

<p><strong>Important</strong> the order of the tables in the figure may differ. Sections and segments have no specified order. Only ELF header has a fixed position, and this gives the offsets to the other headers.</p>

<h2 id="data-representation">Data Representation</h2>

<p>Object file format supports various processors (8, 32 or 64 bits) but it’s intended to be extensible to larger or smaller architectures. Object files therefore represent some control data with machine-independent format, making possible identify object files and interpret contents in a common way. So data used will be always the same regardless of machine on which the file was created:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Size</th>
      <th style="text-align: center">Alignment</th>
      <th style="text-align: center">Purpose</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>Elf32_Addr</em></td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">Unsigned program address</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>Elf32_Half</em></td>
      <td style="text-align: center">2</td>
      <td style="text-align: center">2</td>
      <td style="text-align: center">Unsigned medium integer</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>Elf32_Off</em></td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">Unsigned file offset</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>Elf32_Sword</em></td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">Signed large integer</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>Elf32_Word</em></td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">4</td>
      <td style="text-align: center">Unsigned large integer</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>unsigned char</em></td>
      <td style="text-align: center">1</td>
      <td style="text-align: center">1</td>
      <td style="text-align: center">Unsigned small integer</td>
    </tr>
  </tbody>
</table>

<p>Data structures that object file format defines follow “natural” size and alignment. If necessary, explicit padding is used to ensure 4-byte alignment for 4-byte objects. Data also have alignment from the beginning of the file. An structure containing an <em>Elf32_Addr</em> will be aligned on a 4-byte boundary within the file.</p>

<p><strong>ELF uses no bit fields</strong></p>

<h2 id="character-representations">Character Representations</h2>

<p>When in ELF structure some part mention character constant, the numerical value should follow the 7-bit ASCII guidelines. Character values outside range of 0 to 127 may occupy one or more bytes. Applications can control their own character sets, using different character set extensions for different languages as appropiate. Guidelines:</p>

<ul>
  <li>Character between 0 and 127 correspond to 7-bit ASCII code.</li>
  <li>Multibyte character encodings with values above 127 should contain only bytes with values outside range of 0 to 127.</li>
  <li>Multibyte characters should be self-identifying. That allows, any multibyte character to be inserted between any pair of multibyte characters, without changing characters’ interpretations.</li>
</ul>

<h2 id="elf-header">Elf Header</h2>

<p>Some object file control structures can grow, because ELF header contains their sizes. If object file format changes, a program may encounter control structures that are larger or smaller than expected. Programs might ignore “extra” information.</p>

<p>The structure for this header, can be found in <em>elf_generic_types.h</em> structure <em>Elf_Ehdr</em>:</p>

<ul>
  <li><em>e_ident</em>: mark file as object file, provide machine-independent data to decode and interpret file’s content.</li>
  <li><em>e_type</em>: identifies object file type as relocatable, executable, shared object or core (also a no file type).</li>
  <li><em>e_machine</em>: specifies required architecture for individual file, examples are AT&amp;T WE 32100, SPARC, Intel, MIPS, etc.</li>
  <li><em>e_version</em>: identifies object file version, for the moment <em>EV_NONE</em> and <em>EV_CURRENT</em> are used only.</li>
  <li><em>e_entry</em>: virtual address of the entry point, if no entry point, zero is written here.</li>
  <li><em>e_phoff</em>: program header table’s file offset in bytes.</li>
  <li><em>e_shoff</em>: section header table’s file offset in bytes.</li>
  <li><em>e_flags</em>: processor-specific flags associated with file. Flag names take form <em>EF_machine_flag</em></li>
  <li><em>e_ehsize</em>: ELF header’s size in bytes.</li>
  <li><em>e_phentsize</em>: size in bytes of one entry in file’s program header table, all entries have same size.</li>
  <li><em>e_phnum</em>: number of entries in program header table. So <em>e_phentsize</em> x <em>e_phnum</em> gives table’s size in bytes.</li>
  <li><em>e_shentsize</em>: section header’s size in bytes. All entries are same size.</li>
  <li><em>e_shnum</em>: number of entries in section header table. So <em>e_shentsize</em> x <em>e_shnum</em> gives table’s size in bytes.</li>
  <li><em>e_shstrndx</em>: holds section header table index of entry associated with section name string table.</li>
</ul>

<h2 id="elf-identification">Elf Identification</h2>

<p>Initial bytes of file specify how to interpret the file, independent of the processor on which the inquiry is made and independent of file’s remaining contents. Initial bytes of ELF header (and object file) correspond to <em>e_ident</em> member:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Value</th>
      <th style="text-align: left">Purpose</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>EI_MAG0</em></td>
      <td style="text-align: center">0</td>
      <td style="text-align: left">File identification</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_MAG1</em></td>
      <td style="text-align: center">1</td>
      <td style="text-align: left">File identification</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_MAG2</em></td>
      <td style="text-align: center">2</td>
      <td style="text-align: left">File identification</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_MAG3</em></td>
      <td style="text-align: center">3</td>
      <td style="text-align: left">File identification</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_CLASS</em></td>
      <td style="text-align: center">4</td>
      <td style="text-align: left">File class</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_DATA</em></td>
      <td style="text-align: center">5</td>
      <td style="text-align: left">Data encoding</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_VERSION</em></td>
      <td style="text-align: center">6</td>
      <td style="text-align: left">File version</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_PAD</em></td>
      <td style="text-align: center">7</td>
      <td style="text-align: left">Start of padding bytes</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>EI_NIDENT</em></td>
      <td style="text-align: center">16</td>
      <td style="text-align: left">size of <em>e_ident[]</em></td>
    </tr>
  </tbody>
</table>

<p>From <em>EI_MAG0</em> to <em>EI_MAG3</em> we have the “magic number”, which idenity ELF object, contain next values:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Value</th>
      <th style="text-align: left">Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>ELFMAG0</em></td>
      <td style="text-align: center"><em>0x7f</em></td>
      <td style="text-align: left">e_ident[EI_MAG0]</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>ELFMAG1</em></td>
      <td style="text-align: center"><em>‘E’</em></td>
      <td style="text-align: left">e_ident[EI_MAG1]</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>ELFMAG2</em></td>
      <td style="text-align: center"><em>‘L’</em></td>
      <td style="text-align: left">e_ident[EI_MAG2]</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>ELFMAG3</em></td>
      <td style="text-align: center"><em>‘F’</em></td>
      <td style="text-align: left">e_ident[EI_MAG3]</td>
    </tr>
  </tbody>
</table>

<p><em>EI_CLASS</em> identifies file’s class or capacity. The class <em>ELFCLASS32</em> supports machines with files and virtual address spaces up to 4 gigabytes; it uses basic types defined above. <em>ELFCLASS64</em> is incomplete and refers to 64-bit architectures. Other classes will be necessary, with different basic types and sizes for object file data.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Value</th>
      <th style="text-align: left">Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>ELFCLASSNONE</em></td>
      <td style="text-align: center">0</td>
      <td style="text-align: left">Invalid class</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>ELFCLASS32</em></td>
      <td style="text-align: center">1</td>
      <td style="text-align: left">32-bit objects</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>ELFCLASS64</em></td>
      <td style="text-align: center">2</td>
      <td style="text-align: left">64-bit objects</td>
    </tr>
  </tbody>
</table>

<p>The value <em>EI_DATA</em> specifies encoding of processor-specific data (little endian or big endian)</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Value</th>
      <th style="text-align: left">Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>ELFDATANONE</em></td>
      <td style="text-align: center">0</td>
      <td style="text-align: left">Invalid data encoding</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>ELFDATA2LSB</em></td>
      <td style="text-align: center">1</td>
      <td style="text-align: left">Little endian</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>ELFDATA2MSB</em></td>
      <td style="text-align: center">2</td>
      <td style="text-align: left">Big endian</td>
    </tr>
  </tbody>
</table>

<p><em>EI_VERSION</em> os ELF header version number. As said previously it must be <em>EV_CURRENT</em>.</p>

<p><em>EI_PAD</em> beginning of unused bytes. Bytes reserved and set to zero; programs that read object files should ignore them.</p>

<h2 id="sections">Sections</h2>

<p>Object file’s section header table lets one locate all file’s sections. Section header is an array of <em>Elf32_Shdr</em> structures. Section header table index is a subscript into this array. ELF header’s <em>e_shoff</em> gives offset from beginning of file to section header table; <em>e_shnum</em> gives number of entries section header table contains; <em>e_shentsize</em> gives size in bytes of each entry.</p>

<p>There are some special section table header indexes reserved, and no sections exist for them:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>SHN_UNDEF</em></td>
      <td style="text-align: center">0</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>SHN_LORESERVE</em></td>
      <td style="text-align: center">0xff00</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>SHN_LOPROC</em></td>
      <td style="text-align: center">0xff00</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>SHN_HIPROC</em></td>
      <td style="text-align: center">0xff1f</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>SHN_ABS</em></td>
      <td style="text-align: center">0xfff1</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>SHN_COMMON</em></td>
      <td style="text-align: center">0xfff2</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>SHN_HIRESERVE</em></td>
      <td style="text-align: center">0xffff</td>
    </tr>
  </tbody>
</table>

<ul>
  <li><em>SHN_UNDEF</em>: undefined, missing, irrelevant or meaningless. Exist an index 0 as it starts the section indexes by 0.</li>
  <li><em>SHN_LORESERVE</em>: lower bound of range of reserved indexes.</li>
  <li><em>SHN_LOPROC</em>-<em>SHN_HIPROC</em>: values in inclusive range, reserved for processor-specific semantics.</li>
  <li><em>SHN_ABS</em>: absolute values for corresponding reference. Symbols defined relative to section number <em>SHN_ABS</em> have absolute values, not affected by relocation.</li>
  <li><em>SHN_COMMON</em>: Symbols defined relative to this section are common symbols (e.g. unallocated C external variables).</li>
  <li><em>SHN_HIRESERVE</em>: upper bound of range of reserved indexes. Values do not reference section header table. Section header table does not contain entries for reserved indexes.</li>
</ul>

<p>Section contains all information in object file (except ELF header, program header table and section header table). Object files’ sections satisfy conditions:</p>

<ul>
  <li>Every section has exactly one section header describing it. Can exist section header without section.</li>
  <li>Each section occupies one contiguous sequence of bytes within a file.</li>
  <li>Sections in a file may not overlap. No byte in file resides in more than one section.</li>
  <li>Object file may have inactive space. Various headers and sections might not “cover” every byte in object file.</li>
</ul>

<p>Structure of section header can be found in <em>elf_generic_types.h</em> in structure <em>Elf_Shdr</em>:</p>

<ul>
  <li><em>sh_name</em>: name of section; index into section header string table section, location of null-terminated string.</li>
  <li><em>sh_type</em>: categorizes section’s contents and semantics. Different values can be used for sh_type:
    <ul>
      <li><em>SHT_NULL</em> (0): value marks section header as inactive; no associated section. Other members may have undefined values.</li>
      <li><em>SHT_PROGBITS</em> (1): Section holds information defined by program, format and meaning determined by program. This section exist on disk.</li>
      <li><em>SHT_SYMTAB</em> (2) and <em>SHT_DYNSYM</em> (11):  symbol tables (useful for parsing symbols).</li>
      <li><em>SHT_STRTAB</em>: string table. Three different can be found by name: .dynstr (Dynamic Symbols names), .strtab (Symbols names), .shstrtab (section header names).</li>
      <li><em>SHT_RELA</em>: Relocation entries with explicit addends (type <em>Elf32_Rela</em>). Object file may have multiple relocation sections.</li>
      <li><em>SHT_HASH</em>: symbol hash table.</li>
      <li><em>SHT_DYNAMIC</em>: Information for dynamic linking.</li>
      <li><em>SHT_NOTE</em>: information that marks file in some way.</li>
      <li><em>SHT_NOBITS</em>: type that occupies no space in the file, only in memory (example .bss), <em>sh_offset</em> contains conceptual file offset.</li>
      <li><em>SHT_REL</em>: relocation entries without explicit addends (type <em>Elf32_Rel</em>).</li>
      <li><em>SHT_SHLIB</em>: reserved without unspecified semantics.</li>
      <li><em>SHT_LOPROC</em> to <em>SHT_HIPROC</em>: values in this range, reserved for processor-specific semantics.</li>
      <li><em>SHT_LOUSER</em>: lower bound of range of indexes reserved for application programs.</li>
      <li><em>SHT_HIUSER</em>: upper bound of range of indexes reserved for application programs. Section types between previous and this one, can be used without conflicting with current or future system-defined section names.</li>
    </ul>
  </li>
</ul>

<p>As we said there was an index 0, but all its values are 0, <em>sh_type</em> equals to <em>SHT_NULL</em> and <em>sh_link</em> equals to <em>SHN_UNDEF</em>.</p>

<ul>
  <li><em>sh_flags</em>: miscellaneous attributes. This are 1 bit flag, values can be:
    <ul>
      <li><em>SHF_WRITE</em> (0x1): data should be writable during process execution.</li>
      <li><em>SHF_ALLOC</em> (0x2): section occupies memory during process execution.</li>
      <li><em>SHF_EXECINSTR</em> (0x4): section contains executable machine instructions.</li>
      <li><em>SHF_MASKPROC</em> (0xf0000000): All bits in this mask are reserved for processor-specific semantics.</li>
    </ul>
  </li>
  <li>
    <p><em>sh_addr</em>: if section <strong>appear in memory image</strong> of process, member gives address which section’s first byte should reside. Otherwise, 0.</p>
  </li>
  <li>
    <p><em>sh_offset</em>: byte offset from beginning of file to first byte in section. A section type <em>SHT_NOBITS</em> <strong>occupies no space in file</strong>, its <em>sh_offset</em> locates conceptual placement in file.</p>
  </li>
  <li><em>sh_size</em>: section size in bytes.</li>
  <li><em>sh_link</em>: section header table index link (points to another section), interpretation depends on section type.</li>
</ul>

<p>Different interpetation exist from these two section types, next table summarize the type, the value for link, and the value for info:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left"><em>sh_type</em></th>
      <th style="text-align: left"><em>sh_link</em></th>
      <th style="text-align: left"><em>sh_info</em></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left">SHT_DYNAMIC</td>
      <td style="text-align: left">The section header index of the string table used by entries in the section</td>
      <td style="text-align: left">0</td>
    </tr>
    <tr>
      <td style="text-align: left">SHT_HASH</td>
      <td style="text-align: left">The section header index of symbol table to which the hash table applies</td>
      <td style="text-align: left">0</td>
    </tr>
    <tr>
      <td style="text-align: left">SHT_REL   SHT_RELA</td>
      <td style="text-align: left">Section header index of associated symbol table</td>
      <td style="text-align: left">The section header index of section to which relocation applies</td>
    </tr>
    <tr>
      <td style="text-align: left">SHT_SYMTAB   SHT_DYNSYM</td>
      <td style="text-align: left">Information is operating system specific</td>
      <td style="text-align: left">Information is operating system specific</td>
    </tr>
    <tr>
      <td style="text-align: left">other</td>
      <td style="text-align: left"><em>SHN_UNDEF</em></td>
      <td style="text-align: left">0</td>
    </tr>
  </tbody>
</table>

<ul>
  <li><em>sh_info</em>: extra information, interpretation depends on section type.</li>
  <li><em>sh_addralign</em>: address alignment constraints. <em>sh_addr</em> must be congruent to 0, modulo the value of <em>sh_addralign</em>. Only 0 and positive integral powers of two are allowed.</li>
  <li><em>sh_entsize</em>: Some sections hold table of fixed-size entries, such as symbol table. For such a section, member gives size in bytes of each entry, member contains 0 if section does not hold a table of fixed-size entries.</li>
</ul>

<h2 id="special-sections">Special Sections</h2>

<p>Sections pre-defined hold program and control information. Sections used by operating system, different types and attributes for different operating systems.</p>

<p>Executable files = object files + libraries (through linking process). Linker resolves references (subroutines and data references) among different object files, adjusts absolute references in object files, and relocates instructions. Linking and Loading, require information defined in object files, information is stored in specific sections such as <em>.dynamic</em>.</p>

<p>Different set of linking models from operating systems:</p>

<ul>
  <li><em>Static</em>: set of object files, system libraries and library archives statically bound, references are resolved, and executable file is created completely self contained.</li>
  <li><em>Dynamic</em>: set of object files, libraries, system shared resources and shared libraries linked together to create executable. When executable is loaded, other shared resources and dynamic libraries must be available in system for program to run successfully. Method to resolve references at execution time will be explained later.</li>
</ul>

<p>Section exists that support debugging (<em>.debug</em> and <em>.line</em>), and program control (<em>.bss</em>, <em>.data</em>, <em>.rodata</em>).</p>

<ul>
  <li><em>.bss</em>: uninitialized data, contribute to program’s memory image. Data is initialized with zeros. Section occupies no file space, section type <em>SHT_NOBITS</em>.</li>
  <li><em>comment</em>: version control information.</li>
  <li><em>.data</em>: data that contribute to program’s memory image.</li>
  <li><em>.debug</em>: information for symbolic debugging. Reserved for future use.</li>
  <li><em>.dynamic</em>: dynamic linking information, it has attributes such as <em>SHF_ALLOC</em> and <em>SHF_WRITE</em>.</li>
  <li><em>.hash</em>: symbol hash table.</li>
  <li><em>.line</em>: line number information for symbolic debugging, correspondence between source program and machine code.</li>
  <li><em>.note</em>: information in a format later explained.</li>
  <li><em>.rodata</em>: read-only data, commonly contribute to a non-writable segment in process image.</li>
  <li><em>.shstrtab</em>: section names table.</li>
  <li><em>.strtab</em>: strings that represent names associated with symbol table entries.</li>
  <li><em>.symtab</em>: symbol table.</li>
  <li><em>.text</em>: executable instructions of a program.</li>
</ul>

<p>Section names that start with a dot prefix are reserved for system. Applications may use names without prefix to avoid conflicts with system sections. Object file format lets one define sections not in the list above, object file may have more than one section with the same name.</p>

<h2 id="string-table">String table</h2>

<p>default string table, it holds null-terminated character sequences (strings). Object file uses strings to represent symbol and section names, they reference a string as an index to their first byte. First byte of string table is a null byte. Last byte of string table is also a null byte, ensuring null termination for all strings. String whose index is zero specifies either no name or null name, depending on context.</p>

<p>Section header’s <em>sh_name</em> holds index into section header string table section, designed by <em>e_shstrndx</em> member of ELF header.</p>

<h2 id="symbol-table">Symbol Table</h2>

<p>Information needed to locate and relocate program’s symbolic definitions and references. Symbol table index is subscript into this array. Index 0 is first entry in table and serves as undefined symbol index. Structure of symbol is in the file <em>elf_generic_types.h</em> in the struct <em>Elf_Sym</em>:</p>

<ul>
  <li><em>st_name</em>: index into object file’s symbol string table, character representations of symbol names.</li>
  <li><em>st_value</em>: value of associated symbol. Depending on context, it maybe absolute value, address, and so on.</li>
  <li><em>st_size</em>: many symbols have associated sizes. A data object’s size is number of bytes contained in object. Member is 0 if symbol has no size or an unknown size.</li>
  <li><em>st_info</em>: symbol’s type and binding attributes.</li>
</ul>

<p>Next code can be used to get the values from <em>st_info</em>:</p>

<pre><code class="language-C">uint64_t type, bind;

if (is_32_bit_binary())
{
    type = ELF32_ST_TYPE(st_info);
    bind = ELF32_ST_BIND(st_info);
}
else if (is_64_bit_binary())
{
    type = ELF64_ST_TYPE(st_info);
    bind = ELF64_ST_BIND(st_info);
}

switch (type)
{
case STT_NOTYPE:
    printf("NOTYPE ");
    break;
case STT_OBJECT:
    printf("OBJECT ");
    break;
case STT_FUNC:
    printf("FUNC   ");
    break;
case STT_SECTION:
    printf("SECTION");
    break;
case STT_FILE:
    printf("FILE   ");
    break;
case STT_LOPROC:
    printf("LOPROC ");
    break;
case STT_HIPROC:
    printf("HIPROC ");
    break;
}

switch (bind)
{
case STB_LOCAL:
    printf("LOCAL  ");
    break;
case STB_GLOBAL:
    printf("GLOBAL ");
    break;
case STB_WEAK:
    printf("WEAK   ");
    break;
}
</code></pre>

<p>So the info contains a bind, where all symbols with <em>STB_LOCAL</em> precede weak and global symbols. And the type is a general classification for the associated entity.</p>

<ul>
  <li><em>st_other</em>: no defined meaning.</li>
  <li><em>st_shndx</em>: every symbol table entry “defined” in relation to some section; member holds relevant section header table index.</li>
</ul>

<p><strong>Symbol Values</strong></p>

<p>Different interpretations for <em>st_value</em>:</p>

<ul>
  <li>In relocatable files, <em>st_value</em> holds alignment constraints for symbols whose section index is <em>SHN_COMMON</em>.</li>
  <li>In relocatable files, <em>st_value</em> holds a section offset for defined symbol. <em>st_value</em> is an offset from the beginning of the section that <em>st_shndx</em> identifies.</li>
  <li>In executable and shared object files, <em>st_value</em> holds virtual address. To make files’ symbols more useful for dynamic linker, section offset gives way to a virtual address, so it’s easier to work on memory and section number is irrelevant.</li>
</ul>

<h2 id="relocation">Relocation</h2>

<p>Process of connecting symbolic references with symbolic definitions. When a program calls a function, associated call instruction must transfer control to proper destination address at execution. Relocatable files must have information that describes how to modify section contents, allowing executable and shared object files to hold right information for process’s program image. Two types of relocations structures are in <em>elf_generic_types.h</em> in <em>Elf_Rel</em> and <em>Elf_Rela</em>.</p>

<ul>
  <li>
    <p><em>r_offset</em>: location at which to apply relocation action. For relocatable file, value is byte offset from beginning of the section to storage unit affected by relocation. For executable file or shared object, value is virtual address of storage unit affected by relocation (check <strong>Quenya relocation mechanism</strong>).</p>
  </li>
  <li>
    <p><em>r_info</em>: member gives both symbol table index with respect to which relocation must be made, and type of relocation to apply. Example, a call instruction’s relocation entry would hold symbol table index of function being called. If index is <em>STN_UNDEF</em>, undefined symbol index, relocation uses 0 as “symbol value”. Relocation types are processor-specific; description of their behaviour appear in processor supplement.</p>
  </li>
  <li>
    <p><em>r_addend</em>: constant addend used to compute value to be stored into relocatable field.</p>
  </li>
</ul>

<p><strong>Important</strong></p>

<p>Only <em>Elf_Rela</em> entries contain explicit addend. Entries of type <em>Elf_Rel</em> store implicit addend in location to be modified. Depending on processor architecture, one form or other might be necessary or more convenient. Implementation for particular machine may use one form exclusively or either form depending on context.</p>

<p>A relocation section references two other sections: a symbol table and a section to modify. Section header’s values <em>sh_info</em> and <em>sh_link</em> members, specify these relationships. Relocation entries for different object files have slightly different interpretations for <em>r_offset</em> member.</p>

<ul>
  <li>In relocatable files, <em>r_offset</em> holds section offset. Relocation section itself describes how to modify another section in file.</li>
  <li>In executable and shared object files, <em>r_offset</em> holds virtual address. So make relocation entries more useful for dynamic linker.</li>
</ul>

<h1 id="quenya-relocation-mechanism">Quenya relocation mechanism</h1>

<p>From the Learning Linux Binary Analysis we extract the next relocation mechanism from author’s program <em>Quenya</em>:</p>

<pre><code class="language-C">switch(obj.shdr[i].sh_type) /* first going through all the sections checking its type */
{
case SHT_REL: /* Section contains ElfN_Rel records */

    /* Point to the array of relocs */
    rel = (Elf32_Rel *)(obj.mem + obj.shdr[i].sh_offset);

    /* Now go through all of those relocs */
    for (j = 0; j &lt; obj.shdr[i].sh_size / sizeof(Elf32_Rel); j++, rel++)
    {
        /* 
        *   The sh_link from the section of the reloc
        *   points to a symbol section, so we can use
        *   this to point to the symbols
        */
        /* symbol table */
        symtab = (Elf32_Sym *)obj.section[obj.shdr[i].sh_link];

        /* symbol we are applying relocation to */
        symbol = &amp;symtab[ELF32_R_SYM(rel-&gt;r_info)];

        /*
        *   TargetSection = section to apply the reloc
        *   TargetIndex = index of the previous section
        * 
        *   All of them pointed by sh_info of reloc section.
        */
        /* section to modify */
        TargetSection = &amp;obj.shdr[obj.shdr[i].sh_info];
        TargetIndex = obj.shdr[i].sh_info;

        /*
        *   Address or offset where to apply
        *   the relocation, using the base address
        *   of target section, and the offset
        */
        /* target location */
        TargetAddr = TargetSection-&gt;sh_addr + rel-&gt;r_offset;

        /*
        *   Pointer to where to apply the reloc
        */
        /* pointer to relocation target */
        RelocPtr = (Elf32_Addr *)(obj.section[TargetIndex] + rel-&gt;r_offset);

        /*
        *   Get the value we need to modify
        */
        /* relocation value */
        RelVal = symbol-&gt;st_value;
        RelVal += obj.shdr[symbol-&gt;st_shndx].sh_addr;

        printf("0x%08x %s addr: 0x%x\n",RelVal, 
        &amp;SymStringTable[symbol-&gt;st_name], TargetAddr);

        /* 
        *   As the info type depends on the
        *   processor, a macro is needed to
        *   get the type. Then different values
        *   are checked.
        switch (ELF32_R_TYPE(rel-&gt;r_info))
        {
        /* R_386_PC32   2   word32  S + A - P */
        case R_386_PC32:
            *RelocPtr += RelVal;
            *RelocPtr -= TargetAddr;
            break;
        
        /* R_386_32     1   word32  S + A */
        case R_386_32:
            *RelocPtr += RelVal;
            break;
        }
    }
}
</code></pre>

<h1 id="program-loading-and-dynamic-linking">Program Loading and Dynamic Linking</h1>

<p>To execute program, system uses files to create dynamic program representations, or process images. Process image has segments that hold text, data, stack and so on. This section describes object file structures that relate directly to program execution. Primary data structure, program header table, locates segment images within file and contains other information necessary to create memory image for program.
Given object file, system must load it into memory for program to run. After system loads program, it must complete process image resolving symbolic references among object files that compose the process.</p>

<h2 id="program-header">Program Header</h2>

<p>Array of structures, each describing a segment or other information system needs to prepare program for execution. An object file <em>segment</em> contains one or more <em>sections</em>. Program header are meaningful only for executable and shared object files. The offset to the program header table is specified by <em>e_phoff</em>, and the number of structures can be obtained using <em>e_phentsize</em> and <em>e_phnum</em>.</p>

<ul>
  <li><em>p_type</em>: What kind of segment this array element describes, or how to interpret array element’s information.
    <ul>
      <li><em>PT_NULL</em> (0): array element unused, other values are undefined, program loader can ignore these segments.</li>
      <li><em>PT_LOAD</em> (1): loadable segment, described by <em>p_filesz</em> and <em>p_memsz</em>. Bytes from file, mapped to beginning of memory segment. If <em>p_memsz</em> &gt; <em>p_filesz</em> padding is done with value 0. File size may not be larger than memory size. Loadable segment entries in program header table appear in ascending order, sorted on <em>p_vaddr</em> member.</li>
      <li><em>PT_DYNAMIC</em> (2): array element specifies dynamic linking information.</li>
      <li><em>PT_INTERP</em> location and size of a null-terminated path name to invoke as an interpreter.</li>
      <li><em>PT_NOTE</em>: location and size of auxiliary information.</li>
      <li><em>PT_PHDR</em>: location and size of program header table itself, both in file and in memory image. Segment type may not occur more than once in a file, and only if program header table is part of memory image. If present, it must precede any loadable segment entry.</li>
      <li><em>PT_LOPROC</em> to <em>PT_HIPROC</em>: values in this range, reserved for processor-specific semantics.</li>
    </ul>
  </li>
  <li><em>p_offset</em>: offset from beginning of file at which first byte of segment resides.</li>
  <li><em>p_vaddr</em>: Virtual address at which first byte of segment resides in memory.</li>
  <li><em>p_paddr</em>: for system which physical addressing is relevant, member is reserved for segment’s physical address. This member requires operating system specific information.</li>
  <li><em>p_filesz</em>: number of bytes in file image of segment; it may be zero.</li>
  <li><em>p_memsz</em>: number of bytes in memory image of segment.</li>
  <li><em>p_flags</em>: flags relevant to the segment.</li>
  <li><em>p_align</em>: loadable process segments must have congruent values for <em>p_vaddr</em> and <em>p_offset</em>, module page size. Member gives the value to which the segments are aligned in memory and in the file. Value 0 and 1, no alignment required.</li>
</ul>

<h2 id="note-section">Note Section</h2>

<p>Sometimes necessary mark object file with special information that other programs will check for conformance, compatibility, etc. Sections <em>SHT_NOTE</em> and program header of type <em>PT_NOTE</em> can be used for this. Note information in both, holds any number of entries, each is an array of 4-byte words in format of target processor.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    +-----------------------+
    |         namesz        |
    +-----------------------+
    |         descsz        |
    +-----------------------+
    |         type          |
    +-----------------------+
    |         name          |
    |         ...           |
    +-----------------------+
    |         desc          |
    |         ...           |
    +-----------------------+
</code></pre></div></div>

<p><em>namesz</em> and <em>name</em> first namesz bytes in name is a null-terminated character representation of entry’s owner. No formal mechanism for avoiding name conflicts. Convention, vendors use their own name (e.g. XYZ Computer Company). If no name is present, namesz contains 0. Padding is present, if necessary, to ensure 4-byte alignment for descriptor. Padding is not included in namesz.</p>

<p><em>descsz</em> and <em>desc</em> first descsz bytes in desc hold note descriptor. ELF places no constraints on descriptor’s contents. No descriptor present, descsz contains 0, padding is present in case to ensure 4-byte alignment. Padding is not included in descsz.</p>

<p><em>type</em> interpretation of descriptor. Each originator controls its own types. A program must recognize both name and type to “understand” a descriptor. Types must be non-negative. ELF does not define what descriptors mean.</p>

<h2 id="program-loading">Program Loading</h2>

<p>Process by which operating system creates or augments a process image. The manner in which process is accomplished and how page management functions for process are handled are dictated by operating system and processor. (End of notes)</p>

<h2 id="dynamic-linking">Dynamic Linking</h2>

<p>resolves references either at process initialization time and/or at execution time. Some basic mechanisms need to be set up for a particular linkage model to work, there are ELF sections and header elements reserved for this purpose. (End of notes)</p>

<h2 id="special-section-names">Special Section Names</h2>

<h3 id="special-sections-1">Special Sections</h3>

<ul>
  <li><em>.bss</em></li>
  <li><em>.comment</em></li>
  <li><em>.data</em></li>
  <li><em>.data1</em></li>
  <li><em>.debug</em></li>
  <li><em>.dynamic</em></li>
  <li><em>.dynstr</em></li>
  <li><em>.dynsym</em></li>
  <li><em>.fini</em></li>
  <li><em>.got</em></li>
  <li><em>.hash</em></li>
  <li><em>.init</em></li>
  <li><em>.interp</em></li>
  <li><em>.line</em></li>
  <li><em>.note</em></li>
  <li><em>.plt</em></li>
  <li><em>.relname</em></li>
  <li><em>.relaname</em></li>
  <li><em>.rodata</em></li>
  <li><em>.rodata1</em></li>
  <li><em>.shstrtab</em></li>
  <li><em>.strtab</em></li>
  <li><em>.symtab</em></li>
  <li><em>.text</em></li>
</ul>

<h2 id="dynamic-section-names">Dynamic Section Names</h2>

<p><em>_DYNAMIC</em></p>

<h3 id="dynamic-array-tags">Dynamic Array Tags</h3>

<ul>
  <li><em>DT_NULL</em></li>
  <li><em>DT_NEEDED</em></li>
  <li><em>DT_PLTRELSZ</em></li>
  <li><em>DT_PLTGOT</em></li>
  <li><em>DT_HASH</em></li>
  <li><em>DT_STRTAB</em></li>
  <li><em>DT_SYMTAB</em></li>
  <li><em>DT_RELA</em></li>
  <li><em>DT_RELASZ</em></li>
  <li><em>DT_RELAENT</em></li>
  <li><em>DT_STRSZ</em></li>
  <li><em>DT_SYMENT</em></li>
  <li><em>DT_INIT</em></li>
  <li><em>DT_FINI</em></li>
  <li><em>DT_SONAME</em></li>
  <li><em>DT_RPATH</em></li>
  <li><em>DT_SYMBOLIC</em></li>
  <li><em>DT_REL</em></li>
  <li><em>DT_RELSZ</em></li>
  <li><em>DT_RELENT</em></li>
  <li><em>DT_PLTREL</em></li>
  <li><em>DT_DEBUG</em></li>
  <li><em>DT_TEXTREL</em></li>
  <li><em>DT_JMPREL</em></li>
  <li><em>DT_BIND_NOW</em></li>
  <li><em>DT_LOPROC</em></li>
  <li><em>DT_HIPROC</em></li>
</ul>

<h2 id="pre-existing-extensions">Pre-existing Extensions</h2>

<p>Naming conventions for ELF constants that have processor ranges specified. Names such as <em>DT_</em>, <em>PT_</em> for processor specific extensions incorporate name of the processor, example, <em>DT_M32_SPECIAL</em>. Pre-existing processor extensions not using convention will be suported, example, <em>DT_JMP_REL</em>.</p>

<p>Section names reserved for processor architecture are formed placing an abbreviation of architecture name ahead of section name. Name should be taken from architecture names used for <em>e_machine</em>. Example <em>.FOO.psect</em> is <em>psect</em> section defined by FOO architecture. Extensions are called by historical names. Pre-existing extensions: <em>.sdata</em>, <em>.tdesc</em>, <em>.sbss</em>, <em>.lit4</em>, <em>.lit8</em>, <em>.reginfo</em>, <em>.gptab</em>, <em>.liblist</em>, <em>.conflict</em>.</p>

<h2 id="elf-header-1">ELF Header</h2>

<h3 id="machine-identification">Machine Identification</h3>

<p>For file identification, <em>e_ident</em> in intel requires next values:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Position</th>
      <th style="text-align: left">Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>e_ident[EI_CLASS]</em></td>
      <td style="text-align: left"><em>ELFCLASS32</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>e_ident[EI_DATA]</em></td>
      <td style="text-align: left"><em>ELFDATA2LSB</em></td>
    </tr>
  </tbody>
</table>

<p>Processor identification resides in ELF header’s <em>e_machine</em>, must have value <em>EM_386</em>.
ELF header’s <em>e_flags</em> member holds bit flags associated with file. For intel no flags are defined, so member contains zero.</p>

<h2 id="relocation-1">Relocation</h2>

<h3 id="relocation-types">Relocation Types</h3>

<p>Relocation entries describe how to alter instruction and data fields (bit numbers appear in lower box corners):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+-------------------------------------+
|                                     |
|               WORD32                |
|31                                  0|
+-------------------------------------+
</code></pre></div></div>

<p><em>word32</em> specifies a 32-bit field occupying 4 bytes with arbitrary byte alignment. Values use same byte order as other word values in Intel.</p>

<p>Calculations assume actions are transforming a relocatable file into either an executable or a shared object file. Link editor merges one or more relocatable files to form the output. First devices how to combine and locate input files, then updates the symbol values, finally performs relocation. Relocations applies to executable or shared object files are similar and accomplish same result. Notation:</p>

<ul>
  <li><em>A</em>: addend used to compute the value of the relocatable field.</li>
  <li><em>P</em>: place (section offset or address) of storage unit being relocated (computed using <em>r_offset</em>).</li>
  <li><em>S</em>: means the value of the symbol whose index resides in the relocation entry.</li>
</ul>

<p>A relocation entry’s <em>r_offset</em> value designates offset or virtual address of first byte of the affected storage unit. Relocation type specifies which bits to change and how to calculate their values. Intel architecture uses only <em>Elf32_Rel</em> relocation entries, field to be relocated holds the addend. Addend and computed result use same byte order.</p>

<p><strong>Relocation Types</strong></p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Value</th>
      <th style="text-align: left">Field</th>
      <th style="text-align: left">Calculation</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>R_386_NONE</em></td>
      <td style="text-align: center">0</td>
      <td style="text-align: left">none</td>
      <td style="text-align: left">none</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_32</em></td>
      <td style="text-align: center">1</td>
      <td style="text-align: left">word32</td>
      <td style="text-align: left"><em>S+A</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_PC32</em></td>
      <td style="text-align: center">2</td>
      <td style="text-align: left">word32</td>
      <td style="text-align: left">*S+A-P</td>
    </tr>
  </tbody>
</table>

<h2 id="sections-1">Sections</h2>

<p>The following sections are UNIX System V Release 4 specific:</p>

<p><em>SHT_SYMTAB</em> and <em>SHT_DYNSYM</em>: symbol table. Object file may have only one section of each type, restriction may be relaxed in the future. <em>SHT_SYMTAB</em> provides symbols for link editing, although it may also be used for dynamic linking. It may contain many symbols unnecessary for dynamic linking. Object file may also contain a <em>SHT_DYNSYM</em>, which holds a minimal set of dynamic linking symbols, to have space.</p>

<p><em>SHT_STRTAB</em>: object file may have multiple string table sections.</p>

<p><em>SHT_HASH</em>: all objects participating in dynamic linking must contain a symbol hash table. Currently, an object file may have only one hash table, but restriction may be relaxed in the future.</p>

<p><em>SHT_DYNAMIC</em>: Currently, object file may have only one dynamic section, restriction may be relaxed in the future.</p>

<p>Two members in section header, <em>sh_link</em> and <em>sh_info</em>, hold special information, depending on section type. Symbol table section’s <em>sh_info</em> holds symbol table index for first non-local symbol.</p>

<p><strong>sh_link</strong> and <strong>sh_info</strong> Interpretation.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">sh_type</th>
      <th style="text-align: left">sh_link</th>
      <th style="text-align: left">sh_info</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>SHT_SYMTAB</em> <em>SHT_DYNSYM</em></td>
      <td style="text-align: left">The section header index of the associated string table.</td>
      <td style="text-align: left">One greater than the symbol table index of the last local symbol. (binding <em>STB_LOCAL</em>)</td>
    </tr>
  </tbody>
</table>

<h2 id="special-sections-2">Special Sections</h2>

<p>hold program and control information used in UNIX System V. Sections in list below are used by system and have indicated types and attributes. Most of these sections are required for linking process. Information for dynamic linking provided in <em>.dynsym</em>, <em>.dynstr</em>, <em>.interp</em>, <em>.hash</em>, <em>.dynamic</em>, <em>.rel</em>, <em>.rela</em>, <em>.got</em> and <em>.plt</em>. Contents of some of these sections are processor specific, but all support same linkage model.</p>

<ul>
  <li><em>.dynstr</em> (type: <em>SHT_STRTAB</em>, Attributes: <em>SHF_ALLOC</em>): holds strings needed for dynamic linking, most commonly strings that represent names associated with symbol table entries.</li>
  <li><em>.dynsym</em> (type: <em>SHT_DYNSYM</em>, Attributes: <em>SHF_ALLOC</em>): holds the dynamic linking symbol table.</li>
  <li><em>.fini</em> (type: <em>SHT_PROGBITS</em>, Attributes: <em>SHF_ALLOC+SHF_EXECINSTR</em>): holds executable instructions that contribute to the process termination code. When program exits normally, system executes code in this section.</li>
  <li><em>.init</em> (type: <em>SHT_PROGBITS</em>, Attributes: <em>SHF_ALLOC+SHF_EXECINSTR</em>): holds executable instructions that contribute to process initialization code. When program starts to run, system executes code in this section before calling main program entry point.</li>
  <li><em>.interp</em> (type: <em>SHT_PROGBITS</em>): path name of a program interpreter. If file has a loadable segment that includes section, section’s attributes will include <em>SHF_ALLOC</em> bit, otherwise will be off.</li>
  <li><em>.relname</em> and <em>.relaname</em> (type: <em>SHT_REL</em> and <em>SHT_RELA</em>): hold relocation information. If file has a loadable segment that includes relocation, section’s attributes will include the <em>SHF_ALLOC</em> bit, otherwise will be off. Conventionally, <em>name</em> is supplies by section to which relocations apply. A relocation section for <em>.text</em> normally would have name <em>.rel.text</em> or <em>.rela.text</em></li>
</ul>

<h2 id="symbol-table-1">Symbol Table</h2>

<p><em>st_name</em> if value is non-zero, represents a string table index that gives symbol name. Otherwise symbol table entry has no name.</p>

<pre><code class="language-C">if (elf_dynsym[i].st_name != 0)
{
    if (&amp;DynSymbolStringTable[elf_dynsym[i].st_name])
        printf("%s", &amp;DynSymbolStringTable[elf_dynsym[i].st_name]);
}

if (elf_symtab[i].st_name != 0)
{
    if (&amp;SymbolStringTable[elf_symtab[i].st_name])
        printf("%s", &amp;SymbolStringTable[elf_symtab[i].st_name]);
}
</code></pre>

<p><strong>important to know</strong></p>

<p>Function symbols (those with type <em>STT_FUNC</em>) in shared object files have special significance. When object file references a function from shared object, link editor creates a procedure linkage table entry for referenced symbol. Shared object symbols with types other than <em>STT_FUNC</em> will not be referenced automatically through procedure linkage table.</p>

<p>Global and weak symbols differ in two major ways:</p>

<ul>
  <li>When link editor combines relocatable object files, it does not allow multiple definitions of <em>STB_GLOBAL</em> symbol with same name. On other hand, if defined global symbol exists, appearance of weak symbol with same name will not cause error. Link editor honors global definition and ignores weak ones. Similarly, if common symbol exists (symbol whose <em>st_shndx</em> field holds <em>SHN_COMMON</em>), appearance of weak symbol with same name will not cause error. Link editor honors common definition and ignores weak ones.</li>
  <li>When link editor searches archive libraries, it extracts archive members that contain definitions of undefined global symbols. Member’s definition may be either global or a weak symbol. Link editor does not extract archive members to resolve undefined weak symbols. Unresolved weak symbols have zero value.</li>
</ul>

<h2 id="program-header-1">Program Header</h2>

<p>Following program header information is specific to UNIX System V Release 4.</p>

<ul>
  <li><em>p_paddr</em>: on systems for which physical addressing is relevant, member is reserved for segment’s physical address. It can contains unspecified contents for executable files and shared objects.</li>
  <li><em>p_align</em>: loadable process segments must have congruent values for <em>p_vaddr</em> and <em>p_offset</em>, modulo the page size.</li>
</ul>

<p>Some entries describe process segments; other give supplementary information and do not contribute to process image. Segment entries may appear in any order.</p>

<p>Some <em>p_type</em> values:</p>

<ul>
  <li><em>PT_LOAD</em> (1): array element specifies loadable segment, described by <em>p_filesz</em> and <em>p_memsz</em>.</li>
  <li><em>PT_DYNAMIC</em> (2): array element specifies for dynamic linking information. (check “Dynamic Section”).</li>
  <li><em>PT_INTERP</em> (3): array element specifies location and size of a null-terminated path name to invoke as interpreter. Segment type meaningful for executable files, it may not occur more than once in a file. If it’s present, it must precede any loadable segment entry. (check “Program Interpreter”).</li>
  <li><em>PT_SHLIB</em> (5): reserved but has unspecified semantics.</li>
  <li><em>PT_PHDR</em> (6): array element if present, specifies location and size of program header table itself.</li>
</ul>

<h3 id="base-address">Base Address</h3>

<p>Virtual address in program headers might not represent actual virtual address of program’s memory image. Executable files typically contain absolute code. To let process execute correctly, segments must reside at virtual address used to build executable file. On other hand, shared object segments contain <em>position-independent</em> code. This lets a segment’s virtual address change from one process to another. Though system chooses virtual address for individual processes, it maintains segments’ relative positions. Because <em>position-independent</em> code uses relative addressing between segments, difference between virtual address in memory must match difference between virtual address in file, thus a single constant value for any one executable or shared object in a given process. Difference is the <em>base address</em>. One use of base address is to relocate memory image of program during dynamic linking.
Executable or shared object file’s base address is calculated during execution from three values: virtual memory load address, maximum page size, and lowest virtual address of program’s loadable segment. To compute base address, one determines memory address associated with the lowest <em>p_vaddr</em> value for a <em>PT_LOAD</em> segment. Address is truncated to nearest multiple of maximum page size. Corresponding <em>p_vaddr</em> value is also truncated to nearest multiple of maximum page size. Base address is difference between truncated memory address and truncated <em>p_vaadr</em> value.</p>

<h3 id="segment-permissions">Segment Permissions</h3>

<p>A program to be loaded by system must have at least one loadable segment (not required by file format). When system creates loadable segments’ memory images, it gives access permissions as specified in <em>p_flags</em>:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: right">Value</th>
      <th style="text-align: left">Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>PF_X</em></td>
      <td style="text-align: right"><em>0x1</em></td>
      <td style="text-align: left">Execute</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_W</em></td>
      <td style="text-align: right"><em>0x2</em></td>
      <td style="text-align: left">Write</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_R</em></td>
      <td style="text-align: right"><em>0x4</em></td>
      <td style="text-align: left">Read</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_MASKPROC</em></td>
      <td style="text-align: right"><em>0xf0000000</em></td>
      <td style="text-align: left">Unspecified</td>
    </tr>
  </tbody>
</table>

<p>All bits in <em>PF_MASKPROC</em> are reserved for processor-specific semantics. If meanings are specified, processor supplement explains them.
If a permission bit is 0, type of access is denied. Actual memory permission depend on memory management unit, which may vary from one system to another. Although all flag combinations are valid, system may grant more access than requested. In no case, a segment will have write permission unless it is specified explicitly. Following table shows exact flag interpretation and allowable flag interpretation.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Flag</th>
      <th style="text-align: center">Value</th>
      <th style="text-align: left">Exact</th>
      <th style="text-align: left">Allowable</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left">none</td>
      <td style="text-align: center"><em>0</em></td>
      <td style="text-align: left">All access denied</td>
      <td style="text-align: left">All access denied</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_X</em></td>
      <td style="text-align: center"><em>1</em></td>
      <td style="text-align: left">Execute only</td>
      <td style="text-align: left">Read, execute</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_W</em></td>
      <td style="text-align: center"><em>2</em></td>
      <td style="text-align: left">Write only</td>
      <td style="text-align: left">Read, write, execute</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_W + PF_X</em></td>
      <td style="text-align: center"><em>3</em></td>
      <td style="text-align: left">Write, execute</td>
      <td style="text-align: left">Read, write, execute</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_R</em></td>
      <td style="text-align: center"><em>4</em></td>
      <td style="text-align: left">Read only</td>
      <td style="text-align: left">Read, execute</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_R + PF_X</em></td>
      <td style="text-align: center"><em>5</em></td>
      <td style="text-align: left">Read, execute</td>
      <td style="text-align: left">Read, execute</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_R + PF_W</em></td>
      <td style="text-align: center"><em>6</em></td>
      <td style="text-align: left">Read, write</td>
      <td style="text-align: left">Read, write, execute</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>PF_R + PF_W + PF_X</em></td>
      <td style="text-align: center"><em>7</em></td>
      <td style="text-align: left">Read, write, execute</td>
      <td style="text-align: left">Read write, execute</td>
    </tr>
  </tbody>
</table>

<p>Text segments have read and execute (but not write). Data normally have read, write and execute permissions.</p>

<h3 id="segment-contents">Segment Contents</h3>

<p>An object file segment comprises one or more sections, fact is transparent to program header, also it is immaterial to program loading. Nonetheless, various data must be present for program execution, dynamic linking, and so on. Diagrams below illustrate segment contents in general terms. Order and membership of sections within a segment may vary, processor-specific constraints may alter examples below.</p>

<p><strong>Text Segment</strong></p>

<p>Text segments contain read-only instructions and data, includding following sections. Other sections may also reside in loadable segments.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+-----------------+
|      .text      |
+-----------------+
|      .rodata    |
+-----------------+
|      .hash      |
+-----------------+
|      .dynsym    |
+-----------------+
|      .dynstr    |
+-----------------+
|      .plt       |
+-----------------+
|      .rel.got   |
+-----------------+
</code></pre></div></div>

<p><strong>Data Segment</strong></p>

<p>Data segments contain writable data and instructions, includding the following sections:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+-----------------+
|      .data      |
+-----------------+
|      .dynamic   |
+-----------------+
|      .got       |
+-----------------+
|      .bss       |
+-----------------+
</code></pre></div></div>

<p>A <em>PT_DYNAMIC</em> program header element points at <em>.dynamic</em> section (explained later). <em>.got</em> and <em>.plt</em> sections also hold information related to position-independent code and dynamic linking. Although <em>.plt</em> appeas in text segment, it may reside in a text or data segment, depending on the processor.</p>

<p>The <em>.bss</em> section has type <em>SHT_NOBITS</em>. Although it occupies no space in file, it contributes to segment’s memory image. Normally, uninitialized data reside at the end of the segment, making <em>p_memsz</em> larger than <em>p_filesz</em>.</p>

<h1 id="dynamic-linking-based-on-elf-specification">Dynamic Linking (Based on ELF Specification)</h1>

<h2 id="program-interpreter">Program Interpreter</h2>

<p><strong>Executable</strong> file that participates in dynamic linking, shall have a <em>PT_INTERP</em> program header element. During exec syscall, system retrieves a path name from <em>PT_INTERP</em> segment and creates initial process image from interpreter file’s segments. Instead of using original executable file’s segment images, system composes a memory image for the interpreter. Then, is the interpreter’s responsability to receive control from system and provide an environment for application program.
Interpreter receives control in one of two ways. First, it may receive a file descriptor to read executable file, positioned at the beginning. It can use file descriptor to read and/or map executable file’s segments into memory. Second, depending on executable file format, system may load executable file into memory instead of giving interpreter an open file descriptor. With the possible exception of file descriptor, interpreter’s initial process state matches what executable file would have received. Interpreter itself may not require a second interpreter. Interpreter may be either a shared obejct or an executable file.</p>

<ul>
  <li>A shared object (normal case) loaded as position-independent, with addresses that may vary from one process to another; system creates its segments in dynamic segment area used by <em>mmap</em> and related services. Consequently, a shared object interpreter typically will not conflict with original executable file’s original segment addresses.</li>
  <li>An executable file is loaded at fixed addresses; system creates its segment using virtual addresses from program header table. Consequently, an executable file interpreter’s virtual addresses may collide with first executable file; interpreter is responsible for resolving conflicts.</li>
</ul>

<h2 id="dynamic-linker">Dynamic Linker</h2>

<p>When building an executable file that uses dynamic linking, link editor adds a program header element of type <em>PT_INTERP</em>, telling system to invoke dynamic linker as program interpreter.</p>

<p>Executable file and dynamic linker cooperate to create process image for program, entails following actions:</p>

<ul>
  <li>Adding executable file’s memory segments to process image;</li>
  <li>Adding shared object memory segments to process image;</li>
  <li>Performing relocations for executable file and its shared objects;</li>
  <li>Closing file descriptor used to read executable file, if one was given to dynamic linker.</li>
  <li>Transferring control to program, making it look as if program had received control directly from executable file.</li>
</ul>

<p>Link editor also constructs data that assist dynamic linker for executable and shared object files. These data reside in loadable segments, making them available during execution.</p>

<ul>
  <li><em>.dynamic</em> section with type <em>SHT_DYNAMIC</em> holds various data. Structure residing at beginning of section holds addresses of other dynamic linking information.</li>
  <li><em>.hash</em> with type <em>SHT_HASH</em> holds a symbol hash table.</li>
  <li><em>.got</em> and <em>.plt</em> with type <em>SHT_PROGBITS</em> hold two separate tables: global offset table and procedure linkage table. Programs use the former for position-independent code.</li>
</ul>

<p>Because every UNIX System V conforming program imports the basic system services from a shared object library, dynamic linker participates in every TIS ELF-conforming program execution.
Shared objects may occupy virtual memory addresses that are different from addresses recorded in file’s program header table. Dynamic linker relocates memory image, updating absolute addresses before application gains control. Although absolute address values would be correct if library were loaded at address specified in program header table (normally, not the case).</p>

<p>If process environment contains a variable named <em>LD_BIND_NOW</em> with a non-null value, dynamic linker processes all relocation before transferring control to program. All these environment entries would specify this behavior:</p>

<ul>
  <li><em>LD_BIND_NOW=1</em></li>
  <li><em>LD_BIND_NOW=on</em></li>
  <li><em>LD_BIND_NOW=off</em></li>
</ul>

<p>Otherwise, <em>LD_BIND_NOW</em> does not exist in environment or has null value. Dynamic linker is permitted to evaluate procedure linkage table entries lazily (<strong>lazy binding</strong>), avoiding symbol resolution and relocation overhead for functions that are not called.</p>

<h2 id="dynamic-section">Dynamic Section</h2>

<p>If object file participates in dynamic linking, program header table will have an element of type <em>PT_DYNAMIC</em>. This “segment” contains <em>.dynamic</em> section. Special symbol, <em>__DYNAMIC</em>, labels section, contains an array of structures (Structure <em>Elf_Dyn</em> in <em>elf_generic_types.h</em>).</p>

<p><em>d_val</em>: <em>Elf32_Word</em> object represent values with various interpretations.
<em>d_ptr</em>: <em>Elf32_Word</em> objects represent program virtual addresses. A file’s virtual address might not match memory virtual addresses during execution. When interpreting addresses contained in dynamic structure, dynamic linker computes actual addresses, based on original file value and memory base address. For consistency, files do not contain relocation entries to “correct” addresses in dynamic structure.</p>

<p>Following table summarizes tag requirements for executables and shared objects. If tag is “mandatory”, dynamic linking array must have an entry of that type. Likewise, “optional” means an entry for tag may appear but is not required.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: right">Value</th>
      <th style="text-align: left"><em>d_un</em></th>
      <th style="text-align: left">Executable</th>
      <th style="text-align: left">Shared Object</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>DT_NULL</em></td>
      <td style="text-align: right">0</td>
      <td style="text-align: left">ignored</td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">mandatory</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_NEEDED</em></td>
      <td style="text-align: right">1</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_PLTRELSZ</em></td>
      <td style="text-align: right">2</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_PLTGOT</em></td>
      <td style="text-align: right">3</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_HASH</em></td>
      <td style="text-align: right">4</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">mandatory</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_STRTAB</em></td>
      <td style="text-align: right">5</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">mandatory</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_SYMTAB</em></td>
      <td style="text-align: right">6</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">mandatory</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_RELA</em></td>
      <td style="text-align: right">7</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_RELASZ</em></td>
      <td style="text-align: right">8</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_RELAENT</em></td>
      <td style="text-align: right">9</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_STRSZ</em></td>
      <td style="text-align: right">10</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">mandatory</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_SYMENT</em></td>
      <td style="text-align: right">11</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">mandatory</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_INIT</em></td>
      <td style="text-align: right">12</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_FINI</em></td>
      <td style="text-align: right">13</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_SONAME</em></td>
      <td style="text-align: right">14</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">ignored</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_RPATH</em></td>
      <td style="text-align: right">15</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">ignored</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_SYMBOLIC</em></td>
      <td style="text-align: right">16</td>
      <td style="text-align: left">ignored</td>
      <td style="text-align: left">ignored</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_REL</em></td>
      <td style="text-align: right">17</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_RELSZ</em></td>
      <td style="text-align: right">18</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_RELENT</em></td>
      <td style="text-align: right">19</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">mandatory</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_PLTREL</em></td>
      <td style="text-align: right">20</td>
      <td style="text-align: left"><em>d_val</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_DEBUG</em></td>
      <td style="text-align: right">21</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">ignored</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_TEXTREL</em></td>
      <td style="text-align: right">22</td>
      <td style="text-align: left">ignored</td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_JMPREL</em></td>
      <td style="text-align: right">23</td>
      <td style="text-align: left"><em>d_ptr</em></td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_BIND_NOW</em></td>
      <td style="text-align: right">24</td>
      <td style="text-align: left">ignored</td>
      <td style="text-align: left">optional</td>
      <td style="text-align: left">optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_LOPROC</em></td>
      <td style="text-align: right">0x70000000</td>
      <td style="text-align: left">unspecified</td>
      <td style="text-align: left">unspecified</td>
      <td style="text-align: left">unspecified</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>DT_HIPROC</em></td>
      <td style="text-align: right">0x7fffffff</td>
      <td style="text-align: left">unspecified</td>
      <td style="text-align: left">unspecified</td>
      <td style="text-align: left">unspecified</td>
    </tr>
  </tbody>
</table>

<ul>
  <li><em>DT_NULL</em>: entry with this flag, marks end of <em>_DYNAMIC</em> array.</li>
  <li><em>DT_NEEDED</em>: element holds string table offset of null-terminated string, giving name of a needed library. Offset is index into table recorded in <em>DT_STRTAB</em> entry. Dynamic array may contain multiple entries with this type. Entries’ relative order is significant, though their relation to entries of other types is not. (Search in here imported libraries)</li>
  <li><em>DT_PLTRELSZ</em>: total size in bytes, of relocation entries associated with procedure linkage table. If an entry of type <em>DT_JMPREL</em> is present, a <em>DT_PLTRELSZ</em> must accompany it.</li>
  <li><em>DT_PLTGOT</em>: element holds an address associated with procedure linkage table and/or global offset table.</li>
  <li><em>DT_HASH</em>: address of symbol hash table. Hash table refers to symbol table referenced by <em>DT_SYMTAB</em> element.</li>
  <li><em>DT_STRTAB</em>: address of string table. Symbol names, library names, and other strings reside in this table.</li>
  <li><em>DT_SYMTAB</em>: address of symbol table.</li>
  <li><em>DT_RELA</em>: Address of relocation table. Entries in table have explicit addends, such as <em>Elf32_Rela</em> for 32-bit file class. Object file may have multiple relocation sections. When building relocation table for executable or shared object file, link editor catenates those sections to form a single table. Although sections remain independent in object file, dynamic linker sees a single table. When dynamic linker creates process image for executable file or adds a shared object to process image, it reads relocation table and performs associated actions. If element is present, dynamic structure must also have <em>DT_RELASZ</em> and <em>DT_RELAENT</em> elements. When relocation is “mandatory” for a file, <em>DT_RELA</em> or <em>DT_REL</em> may occur.</li>
  <li><em>DT_RELASZ</em>: total size, in bytes, of <em>DT_RELA</em> relocation table.</li>
  <li><em>DT_RELAENT</em>: size, in bytes, of <em>DT_RELA</em> relocation entry. (Number of entries = <em>DT_RELASZ</em>/<em>DT_RELAENT</em>)</li>
  <li><em>DT_STRSZ</em>: size, in bytes, of the string table.</li>
  <li><em>DT_SYMENT</em>: size, in bytes, of symbol table entry.</li>
  <li><em>DT_INIT</em>: address of initialization function.</li>
  <li><em>DT_FINI</em>: address of termination function.</li>
  <li><em>DT_SONAME</em>: string table offset of a null-terminated string, giving name of shared object. Offset is an index into table recorded in <em>DT_STRTAB</em> entry. (Search in here exported libraries)</li>
  <li><em>DT_RPATH</em>: string table offset of null-terminated search library search path string. Offset is index into table recorded in <em>DT_STRTAB</em> entry.</li>
  <li><em>DT_SYMBOLIC</em>: element’s presence in shared object library alters dynamic linker’s symbol resolution algorithm for references within the library. Instead of starting a symbol search with executable file, dynamic linker starts from shared ombject itself. If shared object fails to supply referenced symbol, dynamic linker searches executable file and other shared objects as usual.</li>
  <li><em>DT_REL</em>: similar to <em>DT_RELA</em>, except its table has implicit addends, such as <em>Elf32_Rel</em> for 32-bit file class. If element is present, dynamic structure must also have <em>DT_RELSZ</em> and <em>DT_RELENT</em> elements.</li>
  <li><em>DT_RELSZ</em>: total size, in bytes, of <em>DT_REL</em> relocation table.</li>
  <li><em>DT_RELENT</em>: size, in bytes, of <em>DT_REL</em> relocation entry. (Number of entries = <em>DT_RELSZ</em>/<em>DT_RELENT</em>)</li>
  <li><em>DT_PLTREL</em>: type of relocation entry to which procedure linkage table refers. <em>d_val</em> member holds <em>DT_REL</em> or <em>DT_RELA</em>, as appropiate. Relocations in procedure linkage table must use same relocation.</li>
  <li><em>DT_DEBUG</em>: used for debugging.</li>
  <li><em>DT_TEXTREL</em>: absence of this signifies that no relocation entry should cause a modification to a non-writaable segment, as specified by segment permissions in program header table. If it is present, one or more relocation entries might request modifications to a non-writable segment, and dynamic linker can prepare accordingly.</li>
  <li><em>DT_JMPREL</em>: If present, this entries <em>d_ptr</em> member holds address of relocation entries associated solely with procedure linkage table. Separating these relocation entries lets dynamic linker ignore them during process initialization, if lazy binding is enabled. If entry is present, related entries of types <em>DT_PLTRELSZ</em> and <em>DT_PLTREL</em> must also be present.</li>
  <li><em>DT_BIND_NOW</em>: if present in shared object or executable, instructs dynamic linker to process all relocations before transferring control to program. Present of entry takes precedence over a directive to use lazy binding for this object when specified through environment or via <em>dlopen(BA_LIB)</em>.</li>
  <li><em>DT_LOPROC</em> to <em>DT_HIPROC</em>: reserved for processor-specific semantics.</li>
</ul>

<h2 id="shared-object-dependencies">Shared Object Dependencies</h2>

<p>When link editor processes an archive library, extracts library members and copies them into output object file. These statically linked services are available during execution without involving dynamic linker. Shared objects provide services, and dynamic linker must attach proper shared object files to process image for execution.</p>

<p>When dynamic linker creates memory segments for object file, dependiendies (entries <em>DT_NEEDED</em> of dynamic structure) tell what shared objects are needed to supply program’s services. By repeatedly connecting referenced shared objects and their dependencies, dynamic linker builds a complete process image. When resolving symbolic references, dynamic linker examines symbol tables with a breadth-first search. It first looks at the symbol table of executable program itself, then symbol tables of <em>DT_NEEDED</em> entries (in order), then at second level <em>DT_NEEDED</em> entries, and so on. Shared object files must be readable by process; other permissions are not required.</p>

<p>Names in the dependency list are copies of <em>DT_SONAME</em> strings or path names of shared objects used to build object file. Example, if link editor builds executable file using one shared object with a <em>DT_SONAME</em> entry of <em>lib1</em> and another shared object library with path name <em>/usr/lib/lib2</em>, executable file will contain <em>lib1</em> and <em>/usr/lib/lib2</em> in its dependency list.</p>

<p>If a shared object name has one or more slash characters anywhere in name (e.g. <em>/usr/lib/lib2</em> above or <em>directory/file</em>), the dynamic linker uses string directly as path name. If name has no slashes, such as <em>lib1</em>, three facilities specify shared object path searching, with following precedence.</p>

<ul>
  <li>First, dynamic array tag <em>DT_RPATH</em> may give a string that holds a list of directories, separated by colons (:). For example, the string <em>/home/dir/lib:/home/dir2/lib:</em> tells dynamic linker to search first directory <em>/home/dir/lib</em>, then <em>/home/dir2/lib</em>, then current directory to find dependencies.</li>
  <li>Second, a variable called <em>LD_LIBRARY_PATH</em> in process environment may hold a list of directories as above, optionally followed by a semicolon (;) and another directory list.</li>
</ul>

<p>All <em>LD_LIBRARY_PATH</em> directories are searched after those from <em>DT_RPATH</em>. Although some programs (such as link editor) treat the lists before and after semicolon differently, dynamic linker doesn’t. Dynamic linker accepts semicolon notation, with semantics described above.</p>

<ul>
  <li>Finally, if other two groups of directories fail to locate desired library, dynamic linker searches <em>/usr/lib</em>.</li>
</ul>

<p><strong>IMPORTANT</strong></p>

<p>For security, dynamic linker ignores environment search specifications for SUID and SGID programs (this would allow an attacker to inject into them). It does search <em>DT_RPATH</em> directories and <em>/usr/lib</em>. Same restriction may be applied to processes that have more than minimal privileges on systems with installed extended security systems.</p>

<h2 id="global-offset-table">Global Offset Table</h2>

<p>absolute addresses in private data. This makes it possible to have addresses available without compromising position-independence and sharability of program text. Table is essential in System V environment for dynamic linking process to work.</p>

<h2 id="procedure-linkage-table">Procedure Linkage Table</h2>

<p>Similar to how global offset table redirects position-independent address calculations to absolute locations, procedure linkage table redirects position-independent function calls to absolute locations. Link editor cannot resolve execution transfers, from one executable or shared object to another. Link editor arranges to have program transfer control to entries in procedure linkage table.</p>

<h2 id="hash-table">Hash Table</h2>

<p>Hash table of <em>Elf32_Word</em> objects support symbol table access. Labels appear below to help explain hash table organization, but they are not part of specification.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+----------------------+
|   nbucket            |
+----------------------+
|   nchain             |
+----------------------+
|   bucket[0]          |
|   ...                |
|   bucket[nbucket-1]  |
+----------------------+
|   chain[0]           |
|   ...                |
|   chain[nchain-1]    |
+----------------------+
</code></pre></div></div>

<p><em>bucket</em> and <em>chain</em> hold symbol table indexes. Chain table entries parallel symbol table. Number of symbol table entries should equal <em>nchain</em>; so symbol table indexes also select chain table entries. A hashing function accepts a symbol name and returns a value that may be used to compute a <em>bucket</em> index. If hashing function returns value x for a name, <em>bucket[x%nbucket]</em> gives an index <em>y</em> into both symbol table and chain table. If symbol table entry is not the one desired, <em>chain[y]</em> gives next symbol table entry with same hash value. One can follow chain links until either selected symbol table entry holds desired name or chain entry contains value <em>STN_UNDEF</em>.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">unsigned</span> <span class="kt">long</span>
<span class="nf">elf_hash</span><span class="p">(</span><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">h</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">g</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">name</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">h</span> <span class="o">=</span> <span class="p">(</span><span class="n">h</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="o">*</span><span class="n">name</span><span class="o">++</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">g</span> <span class="o">=</span> <span class="n">h</span> <span class="o">&amp;</span> <span class="mh">0xf00000000</span><span class="p">)</span>
            <span class="n">h</span> <span class="o">^=</span> <span class="n">g</span> <span class="o">&gt;&gt;</span> <span class="mi">24</span><span class="p">;</span>
        <span class="n">h</span> <span class="o">&amp;=</span> <span class="o">~</span><span class="n">g</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">h</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="initialization-and-termination-functions">Initialization and Termination Functions</h2>

<p>After dynamic linker has built process image and performed relocations, each shared object gets opportunity to execute some initialization code. All shared object initializations happen before executable file gains control.</p>

<p>Before initialization code for any object A, initialization code for any other objects that object A depdens on are called. An object A depends on another object B, if B appears in A’s list of needed objects (<em>DT_NEEDED</em> entries of dynamic structure). Order of initialization for circular dependencies is undefined.</p>

<p>Initialization of objects occurs by recursing through the needed entries of each object. The initialization code for an object is invoked after needed entries for that object have been processed. Order of processing among entries of a particular list of needed objects is unspecified.</p>

<p>Following example, two possible correct orderings which can be generated for example NEEDED lists. In example a.out is dependent on b, d, and e. b is dependent on d and f, while d is dependent on e and g. From this information, a dependency graph can be drawn. Above algorithm on initialization will then allow following specified initialization orderings among others.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>        NEEDED Lists
+-------+   +-------+   +-------+
| a.out |   |   b   |   |   d   |
+---+---+   +---+---+   +---+---+
    |           |           |
    v           v           v
   +++         +++         +++
   |b|         |d|         |e|
   +++         +++         +++
    |           |           |
    v           v           v
   +++         +++         +++
   |d|         |f|         |g|
   +++         +-+         +-+
    |
    v
   +++
   |e|
   +-+


         Dependency Graph

            +-----+
 +----------+a.out+--------+
 |          +--+--+        |
 |             |           |
 v             v           v
+++           +++         +++
|b+----------&gt;+d+--------&gt;+e|
+++           +++         +-+
 |             |
 v             v
+++           +++
|f|           |g|
+-+           +-+


Init Orderings

 +-+    +-+    +-+    +-+    +-+    +-----+
 |e+---&gt;+g+---&gt;+d+---&gt;+f+---&gt;+b+---&gt;+a.out|
 +-+    +-+    +-+    +-+    +-+    +-----+

 +-+    +-+    +-+    +-+    +-+    +-----+
 |g+---&gt;+f+---&gt;+e+---&gt;+d+---&gt;+b+---&gt;+a.out|
 +-+    +-+    +-+    +-+    +-+    +-----+
</code></pre></div></div>

<p>Shared objects may have termination functions, executed with <em>atexit</em> mechanism after base process begins its termination sequence. Order in which dynamic linker calls termination functions is exact reverse order of their corresponding initialization functions. If shared object has termination but no initialization, order is the same as it contains initialization function.</p>

<p>Shared objects designate their initialization and termination functions through <em>DT_INIT</em> and <em>DT_FINI</em> entries in dynamic structure. Typically, code for these functions reside in <em>.init</em> and <em>.fini</em> sections.</p>

<p><strong>IMPORTANT</strong></p>

<p>Although <em>atexit</em> termination processing normally will be done, it’s not garanteed to have executed upon process death. Process will not execute termination processing if it calls <em>_exit</em> or if process dies because it received a signal that it neither caught nor ignored.</p>

<p>Dynamic linker is not responsible callign executable file’s <em>.init</em> section or registering executable file’s <em>.fini</em> section with <em>atexit</em>. Termination functions specified by users via <em>atexit</em> mechanism must be executed before any termination functions of shared objects.</p>

<h1 id="appendix">Appendix</h1>

<p>ELF features and functions that are both Intel Architecture and System V Release 4 dependent.</p>

<h2 id="sections-2">Sections</h2>

<h3 id="special-sections-3">Special Sections</h3>

<p>Varios sections hold program and control information. Next sections are used by system, and have indicated types and attributes.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: left">Type</th>
      <th style="text-align: left">Attributes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>.got</em></td>
      <td style="text-align: left"><em>SHT_PROGBITS</em></td>
      <td style="text-align: left"><em>SHF_ALLOC+SHF_WRITE</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>.plt</em></td>
      <td style="text-align: left"><em>SHT_PROGBITS</em></td>
      <td style="text-align: left"><em>SHF_ALLOC+SHF_EXECINSTR</em></td>
    </tr>
  </tbody>
</table>

<h2 id="symbol-table-2">Symbol Table</h2>

<h3 id="symbol-values">Symbol Values</h3>

<p>If executable contains reference to a function defined in one of its associated shared objects, symbol table for that file will contain an entry for that symbol. <em>st_shndx</em> member of symbol table entry contains <em>SHN_UNDEF</em>. This signals to dynamic linker that symbol definition for that function is not contained in executable file itself. If that symbol has been allocated a procedure linkage table entry in executable file, and <em>st_value</em> member for that symbol table entry is non-zero, value will contain virtual address of first instruction of that procedure linkage table entry. Otherwise, <em>st_value</em> member contains zero.</p>

<h2 id="relocation-2">Relocation</h2>

<h3 id="relocation-types-1">Relocation Types</h3>

<p>Calculations assume actions are transforming a relocatable file into an executable or a shared object file. Link editor merges one or more relocatable files to form the output. It first devices how to combine and locate input files, then updates symbol values, finally performs relocation. Notation:</p>

<p><em>A</em>: addend used to compute value of relocatable field.
<em>B</em>: base address at which shared object has been loaded into memory during execution. Generally, a shared object file is built with a 0 base virtual address, but execution address will be different.
<em>G</em>: offset into global offset table at which address of relocation entry’s symbol will reside during execution.
<em>GOT</em>: address of global offset table.
<em>L</em>: place (section offset or address) of procedure linkage table entry for a symbol. A procedure linkage table entry redirects a function call to proper destination. Link editor builds initial procedure linkage table, and dynamic linker modifies the entries during execution time.
<em>P</em>: place (section offset or address) of storage unit being relocated (computed using <em>r_offset</em>).
<em>S</em>: value of symbol whose index resides in relocation entry.</p>

<p>A relocation entry’s <em>r_offset</em> value designates offset or virtual address of first byte of affected storage unit. Relocation type specifies which bits to change and how to calculate their values. Intel architecture uses only <em>Elf32_Rel</em> relocation entries, field to be relocated holds the addend. In all cases, addend and computed result use same byte order.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Name</th>
      <th style="text-align: center">Value</th>
      <th style="text-align: left">Field</th>
      <th style="text-align: left">Calculation</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>R_386_GOT32</em></td>
      <td style="text-align: center"><em>3</em></td>
      <td style="text-align: left"><em>word32</em></td>
      <td style="text-align: left"><em>G + A</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_PLT32</em></td>
      <td style="text-align: center"><em>4</em></td>
      <td style="text-align: left"><em>word32</em></td>
      <td style="text-align: left"><em>L + A - P</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_COPY</em></td>
      <td style="text-align: center"><em>5</em></td>
      <td style="text-align: left">none</td>
      <td style="text-align: left">none</td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_GLOB_DAT</em></td>
      <td style="text-align: center"><em>6</em></td>
      <td style="text-align: left"><em>word32</em></td>
      <td style="text-align: left"><em>S</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_JMP_SLOT</em></td>
      <td style="text-align: center"><em>7</em></td>
      <td style="text-align: left"><em>word32</em></td>
      <td style="text-align: left"><em>S</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_RELATIVE</em></td>
      <td style="text-align: center"><em>8</em></td>
      <td style="text-align: left"><em>word32</em></td>
      <td style="text-align: left"><em>B + A</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_GOTOFF</em></td>
      <td style="text-align: center"><em>9</em></td>
      <td style="text-align: left"><em>word32</em></td>
      <td style="text-align: left"><em>S + A - GOT</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>R_386_GOTPC</em></td>
      <td style="text-align: center"><em>10</em></td>
      <td style="text-align: left"><em>word32</em></td>
      <td style="text-align: left"><em>GOT + A - P</em></td>
    </tr>
  </tbody>
</table>

<ul>
  <li><em>R_386_GLOB_DAT</em>: used to set a global offset table entry to the address of specified symbol. Special relocation type allows one to determine the correspondence between symbols and global offset table entries.</li>
  <li><em>R_386_JMP_SLOT</em>: link editor creates this relocation type for dynamic linking. Its offset member gives location of a procedure linkage table entry. Dynamic linker modifies the procedure linkage table entry to transfer control to the designated symbol’s address.</li>
  <li><em>R_386_RELATIVE</em>: link editor creates this relocation for dynamic linking. Its offset member gives a location within a shared object that contains a value representing a relative address. Dynamic linker computes virtual address by adding virtual address at which the shared object was loaded to relative address. Relocation entries for this type must specify 0 for symbol table index.</li>
  <li><em>R_386_GOTOFF</em>: relocation type computes difference between a symbol’s value and address of global offset table. It additionally instructs link editor to build global offset table.</li>
  <li><em>R_386_GOTPC</em>: relocation type resembles <em>R_386_PC32</em>, except it uses address of global offset table in its calculation. Symbol referenced in this relocation normally is <em>_GLOBAL_OFFSET_TABLE_</em>, which additionally instructs link editor to build global offset table.</li>
</ul>

<h1 id="program-loading-and-dynamic-linking-1">Program Loading and Dynamic Linking</h1>

<h2 id="program-loading-1">Program Loading</h2>

<p>As system creates a process image, it copies a file’s segment to a virtual memory segment. When system physically reads the file depends on program’s execution behavior, system load, and so on. A process does not require a physical page unless it references logical page during execution, and processes commonly leave many pages unreferenced. Delaying physical reads frequently obviates them, improving system performance. To obtain this efficiency, executable and shared object files must have segment images whose file offsets and virtual addresses are congruent, module page size.</p>

<p>Virtual addresses and file offsets for Intel segments are congruent modulo 4KB (0x1000) or larger powers of 2.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>File Offset      File              Virtual Address
      0  +-------------------------+
         |     ELF Header          |
         +-------------------------+
         |  Program Header Table   |
         +-------------------------+
         |   Other Information     |
         +-------------------------+
    0x100|       Text Segment      | 0x8048100
         |       ...               |
         |      0x2be00 Bytes      | 0x8073eff
         +-------------------------+
  0x2bf00|       Data Segment      | 0x8074f00
         |       ...               |
         |      0x4ee00 Bytes      | 0x8079cff
         +-------------------------+
  0x30d00|   Other Information     |
         |       ...               |
         +-------------------------+
</code></pre></div></div>

<p><strong>Program Header Segments</strong></p>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Member</th>
      <th style="text-align: left">Text</th>
      <th style="text-align: left">Data</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><em>p_type</em></td>
      <td style="text-align: left"><em>PT_LOAD</em></td>
      <td style="text-align: left"><em>PT_LOAD</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>p_offset</em></td>
      <td style="text-align: left"><em>0x100</em></td>
      <td style="text-align: left"><em>0x2bf00</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>p_vaddr</em></td>
      <td style="text-align: left"><em>0x8048100</em></td>
      <td style="text-align: left"><em>0x8074f00</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>p_paddr</em></td>
      <td style="text-align: left"><em>unspecified</em></td>
      <td style="text-align: left"><em>unspecified</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>p_filesz</em></td>
      <td style="text-align: left"><em>0x2be00</em></td>
      <td style="text-align: left"><em>0x4e00</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>p_memsz</em></td>
      <td style="text-align: left"><em>0x2be00</em></td>
      <td style="text-align: left"><em>0x5e24</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>p_flags</em></td>
      <td style="text-align: left"><em>PF_R+PF_X</em></td>
      <td style="text-align: left"><em>PF_R+PF_W+PF_X</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><em>p_align</em></td>
      <td style="text-align: left"><em>0x1000</em></td>
      <td style="text-align: left"><em>0x1000</em></td>
    </tr>
  </tbody>
</table>

<p>Although example’s file offset and virtual addresses are congruent modulo 4KB for both text and data, up to four file pages hold impure text or data.</p>
<ul>
  <li>First text page contains ELF header, program header table and other information.</li>
  <li>Last text page holds a copy of beginning of data.</li>
  <li>First data page has a copy of end of text.</li>
  <li>Last data page may contain file information not relevant to running process.</li>
</ul>

<p>System enforces memory permissions as if each segment were complete and separate; segments’ addresses are adjusted to ensure each logical page in address space has single set of permissions (using the alignment). So in example, region of file holding end of text and beginning of data will be mapped twice: at one virtual address for text and a different virtual address for data.</p>

<p>End of data segment requires special handling for uninitialized data, system defines to begin with zero values. If a file’s last data page includes information not in logical memory page, extraneous data must be set to zero, not unknown content. “Impurities” in other three pages are not logically part of process image. Memory image for program follows, assuming 4KB (0x1000 pages).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Virtual Address   Contents      Segment

     0x8048000+-----------------+
              |  Header Padding |
              |   0x100 Bytes   |
              +-----------------+
     0x8048100|  Text Segment   |
              |                 |
              |     ...         |  Text
              |                 |
              |  0x2be00 Bytes  |
              +-----------------+
     0x8073f00|  Data Padding   |
              |  0x100 Bytes    |
              +-----------------+

              +-----------------+
     0x8074000|  Text Padding   |
              |   0xf00 Bytes   |
              +-----------------+
     0x8074f00|  Data Segment   |
              |                 |
              |      ...        |  Data
              |                 |
              |  0x4e00 Bytes   |
              +-----------------+
     0x8049d00|  Uninitialized  |
              |  Data           |
              |  0x1024 Zero    |
              |  Bytes          |
              +-----------------+
     0x807ad24|  Page Padding   |
              |  0x2dc Zero     |
              |  Bytes          |
              +-----------------+
</code></pre></div></div>

<p>One aspect of segment loading differs between executable files and shared objects. Executable file segments typically contain absolute code. To led process execute correctly, segments must reside at virtual addresses sued to build executable file. System uses <em>p_vaddr</em> values unchanged as virtual addresses.
On the other hand, shared object segments typically contain position-independent code. This lets a segment’s virtual address change from one process to another, without invalidating execution behavior. Though system chooses virtual addresses for processes, it maintains segments relative positions. Because position-independent code uses relative addressing between segments, difference between virtual addresses in memory must match difference between virtual addresses in file.</p>

<h2 id="dynamic-linking-1">Dynamic Linking</h2>

<h3 id="dynamic-section-1">Dynamic Section</h3>

<p>Dynamic section entries give information to dynamic linker. Some of information is processor-specific, including interpretation of some entries in dynamic structure.</p>

<p><em>DT_PLTGOT</em>: this entry’s <em>d_ptr</em> gives address of first entry in global offset table. The first three global offset table entries are reserved, and two are used to hold procedure linkage table information.</p>

<h3 id="global-offset-table-1">Global Offset Table</h3>

<p>Position-independent code cannot contain absolute virtual addresses. Global offset tables hold absolute addresses in private data, making addresses available without compromising position-independence and sharability of program’s text. A program references its global offset table using position-independent addressing and extracts absolute values.</p>

<p>Initially, global offset table holds information as required by relocation entries. After system creates memory segments for a loadable object file, dynamic linker processes relocation entries, some will be type <em>R_386_GLOB_DAT</em> referring to global offset table. Dynamic linker determines associated symbol values, calculates absolute addresses, and sets appropiate memory table entries to proper values. Absolute address unknown when link editor builds object file, dynamic linker knows addresses of all memory segments and calculate absolute addresses of symbol contained therein.</p>

<p>If program requires access to absolute address of a symbol, symbol will have a global offset table entry. Because executable file and shared objects have separate global offset tables, symbol’s address may appear in several tables. Dynamic linker processes all global offset table relocations before giving control to any code in process image, ensuring absolute addresses are available during execution.</p>

<p><strong>IMPORTANT</strong></p>

<p>Table’s entry zero, reserved to hold address of dynamic structure, referenced with symbol <em>_DYNAMIC</em>. This allows the dynamic linker, to find its own dynamic structure without having yet processed its relocation entries. Especially important for dynamic linker, because it must initialize itself without relying on other programs to relocate its memory image. On Intel, entries one and two in global offset table also are reserved.</p>

<p>System may choose different memory segment addresses for same shared object in different programs; it may even choose different library addresses for different execution of same program (protection of ASLR). Nonetheless, memory segments do not change addresses once process image is established. As long as process exists, memory segments are in a fixed virtual addresses.</p>

<p>Global offset table’s format and interpretation are processor specific, for intel architecture:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">extern</span> <span class="n">Elf32_Addr</span> <span class="n">_GLOBAL_OFFSET_TABLE_</span><span class="p">[];</span>
</code></pre></div></div>

<h3 id="function-addresses">Function Addresses</h3>

<p>References to address of a function from executable and shared objects might not resolve to same value. References from within shared objects will normally be resolved by dynamic linker to virtual address of function itself. References from within executable file to a function defined in shared object will normally be resolved by link editor to address of procedure linkage table entry for that function within executable file.</p>

<p>If an executable references a function defined in a shared object, link editor will place address of procedure linkage table entry for function in its associated symbol table entry. Dynamic linker treats symbol table entries specially. If dynamic linker is searching for a symbol, and encounters a symbol table entry for that symbol in executable file, it follows next rules:</p>

<ul>
  <li>If <em>st_shndx</em> member of symbol table entry is not <em>SHN_UNDEF</em>, dynamic linker has found a definition for symbol and uses its <em>st_value</em> member as symbol’s address.</li>
  <li>If <em>st_shndx</em> member is <em>SHN_UNDEF</em> and symbol is type <em>STT_FUNC</em> and <em>st_value</em> is not zero, dynamic linker recognizes entry as special and uses <em>st_value</em> member as symbol’s address.</li>
  <li>Otherwise, dynamic linker considers symbol to be undefined within executable file and continues processing.</li>
</ul>

<p>Some relocations are associated with procedure linkage table entries. Entries are used for direct function calls rather than for references to function addresses. Relocations are not treated in special way described above because dynamic linker must not redirect procedure linkage table entries to point to themselves.</p>

<h2 id="procedure-linkage-table-1">Procedure Linkage Table</h2>

<p>this table redirects position-independent function calls to absolute locations. Link editor cannot resolve execution transfer between executable or shared objects. So link editor arranges to have program transfer control to entries in procedure linkage table. On Intel, the table reside in shared text, but they use addresses in private global offset table. Dynamic linker determines destinations’ absolute addresses and modifies global offset table’s memory. Dynamic linker can redirect entries without compromising position-independence and sharability of program’s text. Each executable and shared object have their own procedure linkage table.</p>

<p>Procedure linka table instructions use different operand addressing modes for absolute code and position-independent code. Interfaces to dynamic linkers are the same.</p>

<p><strong>Absolute Procedure Linkage Table</strong></p>

<pre><code class="language-asm">.PLT0:  pushl got_plus_4
        jmp *got_plus_8
        nop
        nop
.PLT1:  jmp *name1_in_GOT
        pushl $offset
        jmp .PLT0@PC
.PLT2:  jmp *name2_in_GOT
        pushl $offset
        jmp .PLT0@PC
        ...
</code></pre>

<p><strong>Position-Independent Procedure Linkage Table</strong></p>

<pre><code class="language-asm">.PLT0:  pushl 4(%ebx)
        jmp *8(%ebx)
        nop
        nop
.PLT1:  jmp *name1@GOT(%ebx)
        pushl $offset
        jmp .PLT0@PC
.PLT2:  jmp *name2@GOT(%ebx)
        pushl $offset
        jmp .PLT0@PC
</code></pre>

<p><strong>IMPORTANT, HOW FUNCTIONS ARE RESOLVED</strong></p>

<p>Following steps below, dynamic linker and program “cooperate” to resolve symbolic references through PLT and GOT.</p>

<ul>
  <li>When creating memory image, dynamic linker sets second and third entries in got to special values.</li>
  <li>If plt is position-independent, address of got table must reside in %ebx. Each shared object file in process has its own plt, and control transfers to a plt entry only from within same object file. Calling function is responsible for setting got base register before calling plt entry.</li>
  <li>Assume program calls <em>name1</em>, which transfers control to label <em>.PLT1</em>.</li>
  <li>First instruction jumps to address in got entry for <em>name1</em>. Initially this is 0, so jumps to next <em>pushl</em> instruction, not address of <em>name1</em>.</li>
  <li>Program pushes a relocation offset (<em>offset</em> on stack). Relocation offset is 32-bit, non-negative byte offset into relocation table. Relocation entry will have type <em>R_386_JMP_SLOT</em> and its offset will specify got entry used in previous <em>jmp</em>. Relocation entry also contains a symbol table index, telling dynamic linker what symbol is being referenced <em>name1</em> in this case.</li>
  <li>After pushing relocation offset, program jumps to <em>.PLT0</em>, first entry in plt. The <em>pushl</em> places value of second got entry (<em>got_plus_4</em> or 4(%ebx)) on the stack, giving dynamic linker one word of identifying information. Program then jumps to address in third got entry (<em>got_plus_8</em> or 8(%ebx)), which transfers control to dynamic linker.</li>
  <li>When dynamic linker receives control, it unwinds stack, looks at desginated relocation entry, find symbol’s value, stores “real” address for <em>name1</em> in got entry, and transfers control to desired destination.</li>
  <li>Subsequent executions of plt entry will transfer directly to <em>name1</em>, without calling dynamic linker a second time. <em>jmp</em> instruction at <em>.PLT1</em> will transfer to <em>name1</em>, instead of going to <em>pushl</em> instruction.</li>
</ul>

<p><em>LD_BIND_NOW</em> environment variable can change behavior. It value is non-null, dynamic linker evaluates plt entries before transferring control to the program. Dynamic linker processes relocation entries of type <em>R_3862_JMP_SLOT</em> during process initialization. Otherwise, dynamic linker evaluates plt entries lazily, delaying symbol resolution and relocation until first execution of a table entry.</p>

<p><strong>Example PLT</strong></p>

<p>Next code is the plt entries of a binary:</p>

<p><img src="./objdump_plt.png" alt="Objdump PLT" title="Program PLT" /></p>

<p>As we can see the <em>.PLT0</em> push GOT + 8 (second entry), and then jumps to GOT + 10 (third entry) that will make dynamic linker to resolve address of an imported function, the imported function is obtained from the index pushed by next PLTs (0x0, 0x1, 0x2) these indexes, are indexes of <em>.rela.plt</em> section:</p>

<p><img src="./rela_plt.png" alt="Parser .rela.plt" title="Program .rela.plt" /></p>

<p>So from each one, the offset points to its got entry, and when the symbol is resolved through its name, address is written in address given by offset.</p>

<p><img src="./objdump_got.png" alt="Objdump GOT" title="Program GOT" /></p>

<h1 id="elf-dynamic-linking-based-on-learning-linux-binary-analysis">ELF Dynamic Linking (Based on Learning Linux Binary Analysis)</h1>

<p>Used when a program is loaded into memory, dynamic linker loads and binds shared libraries needed to the process space. Dynamic linking is relatively complex. We will demystify some of its complexities and reveal how it works and how can be abused.</p>

<p>Shared libraries are compiled as position-independent and can be easily relocated (this is done using the option -fpic -shared of gcc). Shared library is dynamic ELF object, with <em>e_type</em> (<strong>ELF file type</strong>) equals to <em>ET_DYN</em>. Very similar to executables, but don’t have <em>PT_INTERP</em> segment, as this libraries are loaded by the program interpreter of another binary, and they will not invoke the program interpreter.</p>

<p>When a shared library is loaded into process address space, it musy have any relocations satisfied that reference other shared libraries. Dynamic linker modify <em>GOT</em> of the executable (located in section <em>.got.plt</em>), table of addresses located in data segment. It’s in a writable data segment as it will be modified. Dynamic linker patches the <em>GOT</em> with resolved shared library addresses.</p>

<h2 id="auxiliary-vector">Auxiliary vector</h2>

<p>Program mapped by <em>sys_execve()</em> syscall, executable mapped in and given a stack. Stack for process address space, set up in specific way to pass information to dynamic linker. Particular setup and arrangement of information is known as <strong>auxiliary vector (auxv)</strong>. Bottom of the stack loaded with following information:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>                     ^
                     |
                     |
              +------+------+
              |             |
              |    STACK    |
              |             |
              +-------------+
              |             |
              |    ARGV     |
              |             |
              +-------------+
              |             |
              |   Environ   |
              |             |
              +-------------+
              |             |
              |    AUXV     |
              |             |
              +-------------+

[ARGC][ARGV][ENVP][Auxiliary][.ascii data for argv/envp]
</code></pre></div></div>

<p>Auxiliary vector a series of <em>ElfN_auxv_t</em> structs:</p>

<pre><code class="language-C">typedef struct
{
    uint64_t a_type;        /* Entry type */
    union
    {
        uint64_t a_val;     /* Integer value */
    } a_un;
} Elf64_auxv_t;
</code></pre>

<p>The <em>a_type</em> value describes auxv entry type. Some of the most important entry types needed by dynamic linker:</p>

<pre><code class="language-C">#define AT_EXECFD 2 /* File descriptor of program */

#define AT_PHDR 3 /* Program headers for program */

#define AT_PHENT 4 /* Size of program header entry */

#define AT_PHNUM 5 /* Number of program headers */

#define AT_PAGESZ 6 /* System page size */

#define AT_ENTRY 9 /* Entry point of program */

#define AT_UID 11 /* Real uid */
</code></pre>

<p>Dynamic linker retrieves information from stack about executing program. Linker must know where program headers are, entry point of program, and so on.</p>

<p>Auxiliary vector is gets set up by kernel function called <em>created_elf_tables()</em> <a href="https://github.com/torvalds/linux/blob/master/fs/binfmt_elf.c">binfmt_elf.c</a>.</p>

<p>So execution process from kernel looks like:</p>

<ul>
  <li><em>sys_execve()</em></li>
  <li><em>do_exexcve_common()</em></li>
  <li><em>search_binary_handler()</em></li>
  <li><em>load_elf_binary()</em></li>
  <li><em>create_elf_tables()</em></li>
</ul>

<p>And the next code adds auxv entries (using the previous types):</p>

<pre><code class="language-C">/* At system page size */
NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);

/* 
* At a pointer to the program headers for the program 
* done adding the address where program is loaded and
* the offset to the program header.
*/
NEW_AUX_ENT(AT_PHDR, load_addr + exec-&gt;e_phoff);

/* Size of program header entry */
NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));

/* Number of program headers */
NEW_AUX_ENT(AT_PHNUM, exec-&gt;e_phnum);

/* Interpreter base address */
NEW_AUX_ENT(AT_BASE, interp_load_addr);

/* Entry point of the program */
NEW_AUX_ENT(AT_ENTRY, exec-&gt;e_entry);
</code></pre>

<p>All this data is set onto program stack using a macro in kernel.</p>

<p>So once a program is loaded into memory, and auxiliary vector has been filled in, control is passed to dynamic linker. Dynamic linker resolves symbols and relocations for shared libraries linked into process addess space. By default, executable is dynamically linked with GNU C library libc.so. The command <em>ldd</em> show the shared library dependencies of a given executable.</p>

<h1 id="learning-about-the-pltgot">Learning about the PLT/GOT</h1>

<p><em>PLT</em> (Procedure Linkage Table) and <em>GOT</em> (Global Offset Table) found in executables and shared libraries. We will be focusing on the PLT/GOT of executable. When a program calls a shared library function (strcpy or printf for example), these are not resolved until runtime (<strong>lazy binding</strong>), there must exist a mechanism to dynamically link shared libraries and resolve addresses to shared functions. When a dynamically linked program is compiled, it handles shared library function calls in a way far different from a simple call to a local function.</p>

<p>Example calling a <em>fgets()</em> function in a 32-bit binary, we will see in our code a call to <em>fgets</em> in <em>plt</em>:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>objdump <span class="nt">-d</span> <span class="nb">test</span>
<span class="c">...
</span><span class="gp">8048481:    e8 da fe ff ff      call    8048360&lt;fgets@plt&gt;</span><span class="w">
</span><span class="c">...
</span></code></pre></div></div>

<p>As we can see the call is to the plt entry of fgets, and inside of the plt section we have the next:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>objdump <span class="nt">-d</span> <span class="nb">test</span> | <span class="nb">grep </span>8048360
<span class="c">...
</span><span class="gp">08048360&lt;fgets@plt&gt;</span>:
<span class="go"> 8048360:       ff 25 00 a0 04 08   jmp     *0x804a000 /* Jump into GOT section */
</span><span class="gp"> 8048366:       68 00 00 00 00      push    $</span>0x0
<span class="gp"> 804836b:       e9 e0 ff ff ff      jmp     8048350 &lt;_init+0x34&gt;</span><span class="w">
</span><span class="c">...
</span></code></pre></div></div>

<p>Call to <em>fgets()</em> leads to 8048360, this is an indirect jump to the address stored at 0x804a000 in preceding disassembled code output. This address is a <em>GOT</em> entry that holds address to actual <em>fgets()</em> function in libc shared library.
<strong>Lazy Binding</strong> this is a feature where the first time a function is called, its address has not been resolved yet by dynamic linker. Functions are not resolved at loading time. Instead, functions will be resolved as they are called, possible thanks to <em>.plt</em> and <em>.got.plt</em> sections (procedure linkage table, and global offset table). Behavior can be changed with <em>strict linking</em> with environment variable <em>LD_BIND_NOW</em> so dynamic linking happens at program loading time. Lazy linking increases performance at load time, but can be unpredictable since a linking error may not occur until after program has been running for some time (not really common).</p>

<p>We can check the relocation entry for <em>fgets()</em>:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>readelf <span class="nt">-r</span> <span class="nb">test</span>
<span class="go">Offset      Info        Type                SymValue        SymName
</span><span class="c">...
</span><span class="go">0804a000    0000107     R_386_JUMP_SLOT     00000000        fgets
</span><span class="c">...
</span></code></pre></div></div>

<p>Relocation offset is exactly the same address of where PLT fgets jumps into (0x804a000). Assuming <em>fgets()</em> is called for the first time, dynamic linker has to resolve address, and place value into the <em>GOT</em> entry.
This is what the <em>GOT</em> contains:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">08049ff4 &lt;_GLOBAL_OFFSET_TABLE_&gt;</span>:
<span class="go">8049ff4: 28 9f 04 08 00 00      sub %bl,0x804(%edi)
8049ffa: 00 00                  add %al,(%eax)
8049ffc: 00 00                  add %al,(%eax)
8049ffe: 00 00                  add %al,(%eax)
</span><span class="gp">804a000: 66 83 04 08 76         addw $</span>0x76,<span class="o">(</span>%eax,%ecx,1<span class="o">)</span>
<span class="gp">804a005: 83 04 08 86            addl $</span>0xffffff86,<span class="o">(</span>%eax,%ecx,1<span class="o">)</span>
<span class="gp">804a009: 83 04 08 96            addl $</span>0xffffff96,<span class="o">(</span>%eax,%ecx,1<span class="o">)</span>
<span class="go">804a00d: 83                     .byte 0x83
</span><span class="gp">804a00e: 04 08                  add $</span>0x8,%al
</code></pre></div></div>

<p>The address 0x0804a000 contains the value: 0x08048366, which is the address in the PLT after the <em>fgets()</em> jump, this is a <em>push $0x0</em> instruction. That push is the push for the GOT entry for <em>fgets()</em> onto the stack. GOT entry offset for <em>fgets()</em> is 0x0, this is the first GOT entry reserved for a shared library symbol value, but this is the fourth GOT entry, GOT[3]. No shared library is set into GOT[0] and they begin at GOT[3], the first three are reserved:</p>

<ul>
  <li>GOT[0]: address that points to dynamic segment of executable, used by dynamic linker for extracting dynamic linking-related information.</li>
  <li>GOT[1]: address of <em>link_map</em> structure, used by dynamic linker to resolve symbols.</li>
  <li>GOT[2]: address to dynamic linkers <em>_dl_runtime_resolve()</em> function that resolves actual symbol address for shared library function.</li>
</ul>

<p>Last instruction in <em>fgets()</em> in PLT is <em>jmp 8048350 &lt;_init+0x34&gt;</em>. Address points to very first PLT entry in every executable, the <em>PLT-0</em>.</p>

<p><em>PLT-0</em> contains following code:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="go">8048350: ff 35 f8 9f 04 08      pushl 0x8049ff8
8048356: ff 25 fc 9f 04 08      jmp *0x8049ffc
804835c: 00 00                  add %al,(%eax)
</span></code></pre></div></div>

<p>The first <em>pushl</em> pushes the address of GOT[1] (the link_map structure). Then the <em>jmp *0x8049ffc</em> is an indirect jump into third GOT entry (GOT[2]) that it contains the address to dynamic linkers <em>_dl_runtime_resolve()</em>, therefore transferring control to dynamic linker and resolving address for <em>fgets()</em>. Once address is resolved is written into address 0x804a000 of the <em>GOT</em> and next calls to <em>fgets@PLT</em> will directly jump to the <em>fgets</em> address.</p>

<h1 id="dynamic-segment-where-most-of-important-things-from-elf-are">Dynamic Segment (Where most of important things from ELF are)</h1>

<p>The dynamic segment has a section header referencing it, but it has a program header because it must be found during runtime by dynamic linker and section headers are not loaded into memory.</p>

<p>Dynamic segment is an array of this type of struct:</p>

<pre><code class="language-C">typedef struct {
    Elf32_Sword d_tag;
    union {
        Elf32_Word d_val;
        Elf32_Addr d_ptr;
    } d_un;
} Elf32_Dyn;
</code></pre>

<p><em>d_tag</em> field contains a tag that matches one of numerous definitions that can be found in ELF man. Some of the most important one:</p>

<ul>
  <li><strong>DT_NEEDED</strong>: string table offset to name of Interpreter or shared library.</li>
  <li><strong>DT_SYMTAB</strong>: Address of dynamic symbol table, also known by its section name <em>.dynsym</em>, and its <em>sh_type</em> SHT_DYNSYM.</li>
  <li><strong>DT_HASH</strong>: Address of symbol hash table; known by its section name <em>.hash</em> (or <em>.gnu.hash</em>).</li>
  <li><strong>DT_STRTAB</strong>: address of symbol string table, also known by its section name <em>.dynstr</em>.</li>
  <li><strong>DT_PLTGOT</strong>: address of global offset table.</li>
</ul>

<p>Using these dynamic tags, is possible to recover in memory some of the section headers, as these are not loaded, but some of them can be extracted with the dynamic segment values.</p>

<p><em>d_val</em> member holds an integer value that has various interpretations, such as size of relocation entry to give one instance.
<em>d_ptr</em> virtual memory address that can point to various locations needed by linker; good example, address to symbol table for <em>d_tag</em> <em>DT_SYMTAB</em>.</p>

<p>Dynamic linker utilizes the <em>d_tags</em> to locate different parts of dynamic segment that contain a reference to a part of executable through <em>d_tag</em> such as <em>DT_SYMTAB</em>, which has a <em>d_ptr</em> to give virtual address to symbol table.</p>

<p>When dynamic linker is mapped into memory, first handles any of its own relocations (if necessary) as the dynamic linker is a shared library itself. Then looks executable program’s dynamic segment and searches for <em>DT_NEEDED</em> tags that contain pointers to strings or pathnames of necessary shared libraries. When it maps a needed shared library into memory, it accesses library’s dynamic segment and adds library’s dsymbol table to a chain of symbol tables that exists to hold symbol tables for each mapped library.</p>

<p>Linker creates struct <em>link_map</em> entry for each shared library, stores it in a linked list:</p>

<pre><code class="language-C">struct link_map
{
    ElfW(Addr)  l_addr;                 /* Base address shared object is loaded at. */
    char *l_name;                       /* Absolute file name object was found in */
    ElfW(Dyn)   *l_ld;                  /* Dynamic section of shared object */
    struct link_map *l_next, *l_prev;   /* Chain of loaded objects. */
};
</code></pre>

<p>Once linker has finished building its list of dependencies, it handles relocations on each library, similar to relocation discussed earlier, as well as fixing up GOT of each shared library. <strong>Lazy linking</strong> applies to PLT/GOT of shared libraries, so GOT relocations (of type R_386_JMP_SLOT) won’t happen until point when a function has actually been called.</p>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Reverse Engineering" /><category term="Linux" /><category term="ELF" /><category term="Linux" /><category term="Binary Analysis" /><summary type="html"><![CDATA[My personal notes about the ELF file format]]></summary></entry><entry><title type="html">Notes about Linux ptrace syscall</title><link href="https://fare9.github.io/reverse%20engineering/linux/ptrace-notes/" rel="alternate" type="text/html" title="Notes about Linux ptrace syscall" /><published>2024-06-16T00:00:00+00:00</published><updated>2024-06-16T14:55:00+00:00</updated><id>https://fare9.github.io/reverse%20engineering/linux/ptrace-notes</id><content type="html" xml:base="https://fare9.github.io/reverse%20engineering/linux/ptrace-notes/"><![CDATA[<h1 id="ptrace">ptrace</h1>

<p>this system call is highly used when analyzing, debugging, reverse engineering, and modifying programs that use <em>ELF</em> format. <em>ptrace</em> allows us to attach to a process and access code, data, stack, heap, and registers.</p>

<p>Once <em>ELF</em> is completely mapped, we can attach to process, parse or modify <em>ELF</em> similarly as we do in file on disk. <em>ptrace</em> gives access the program instead of using <em>open/mmap/read/write</em> calls.</p>

<p><em>ptrace</em> gives full control over program’s execution flow, this allows memory virus infection, virus analysis or even detection of userland memory rootkits, hotpatching, reverse engineering.</p>

<h2 id="importance-of-ptrace">Importance of ptrace</h2>

<p>Someone can attach to a process that they own and modify, analyze, reverse, and debug it. <em>gdb</em>, <em>strace</em>, and <em>ltrace</em> make use of <em>ptrace</em>. It gives a programmer ability to attach to a process and modify the memory, which can include injecting and modifying data structures such as <strong>Global Offset Table (GOT)</strong> for shared library redirection.</p>

<h2 id="ptrace-requests">ptrace requests</h2>

<p><em>ptrace</em> system call has a <em>libc</em> wrapper, you may include <em>ptrace.h</em> and call <em>ptrace</em> while passing it a request and a process ID.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;sys/ptrace.h&gt;</span><span class="cp">
</span>
<span class="kt">long</span> <span class="nf">ptrace</span><span class="p">(</span><span class="k">enum</span> <span class="n">__ptrace_request</span> <span class="n">request</span><span class="p">,</span> <span class="n">pid_t</span> <span class="n">pid</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">);</span>
</code></pre></div></div>

<h2 id="request-types-enum-__ptrace_request">Request Types (enum __ptrace_request)</h2>

<table>
  <thead>
    <tr>
      <th style="text-align: center">Request</th>
      <th style="text-align: left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center"><em>PTRACE_ATTACH</em></td>
      <td style="text-align: left">Attach to process specified by <em>pid</em>, making it a tracee of calling process. Tracee is sent a <em>SIGSTOP</em> signal, but will not have stopped by completion of this call. Use <em>waitpid</em> to wait for tracee to stop.</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_TRACEME</em></td>
      <td style="text-align: left">Indicates this process is to be traced by its parent. A process shouldn’t make this if its parent isn’t expecting to trace it.</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_PEEKTEXT</em> <em>PTRACE_PEEKDATA</em> <em>PTRACE_PEEKUSER</em></td>
      <td style="text-align: left">Allow tracing process to read from a virtual memory address within traced process image; we can read entire text or data segment into a buffer for analysis. No difference in implementation between these requests.</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_POKETEXT</em> <em>PTRACE_POKEDATA</em> <em>PTRACE_POKEUSER</em></td>
      <td style="text-align: left">Requests allow tracing process to modify any location within traced process image.</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_GETREGS</em></td>
      <td style="text-align: left">Allows tracing process to get a copy of traced process’s registers. Each thread context has its own register set.</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_SETREGS</em></td>
      <td style="text-align: left">Allows tracing process to set new register values for traced process, allowing modifying for example instruction pointer, to point a shellcode</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_CONT</em></td>
      <td style="text-align: left">Tells stopped traced process to resume execution</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_DETACH</em></td>
      <td style="text-align: left">resumes traced process and detaches from it</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_SYSCALL</em></td>
      <td style="text-align: left">Request resumes traced process but arranges for it to stop at entrance/exit of next syscall. Allows us to inspect arguments for syscall and even modify them. <em>ptrace</em> request heavily used in code for a program called <em>straced</em>, which traces all system calls when a program runs</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_SINGLESTEP</em></td>
      <td style="text-align: left">Resumes process but stops it after next instruction. Single stepping allows a debugger to stop after every instruction executed. Allows a user to inspect values of registers and state of process after each instruction</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_GETSIGINFO</em></td>
      <td style="text-align: left">Retrieves information about signal that caused the stop. It retrieves a copy of <em>siginfo_t</em> structure, this can be modified and set (with next request)</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_SETSIGINFO</em></td>
      <td style="text-align: left">Sets signal information. This will affect only signals that would normally be delivered to tracee and would be caught by the tracer (<em>addr</em> ignored)</td>
    </tr>
    <tr>
      <td style="text-align: center"><em>PTRACE_SETOPTIONS</em></td>
      <td style="text-align: left">sets <em>ptrace</em> options from <em>data</em> (<em>addr</em> ignored). Data is interpreted as a bitmask of options.</td>
    </tr>
  </tbody>
</table>

<p>Two terms:</p>
<ul>
  <li><em>tracer</em> process doing the tracing (invoking <em>ptrace</em>).</li>
  <li><em>tracee</em> or <em>traced</em>: program being traced by tracer.</li>
</ul>

<h2 id="the-process-register-state-and-flags">The process register state and flags</h2>

<p>Depending on the architecture we are going to trace we’re gonna have different struct of registers, but mainly we will have general-purpose registers, segmentation registers, stack pointer, CPU flags, and TLS registers:</p>

<p><strong>x86-64</strong></p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">user_regs_struct</span>
<span class="p">{</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r15</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r14</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r13</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r12</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rbp</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rbx</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r11</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r10</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r9</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">r8</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rax</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rcx</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rdx</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rsi</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rdi</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">orig_rax</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rip</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">cs</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">eflags</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">rsp</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">ss</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">fs_base</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">gs_base</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">ds</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">es</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">fs</span><span class="p">;</span>
  <span class="n">__extension__</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="kt">int</span> <span class="n">gs</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p><strong>x86-32</strong></p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">user_regs_struct</span>
<span class="p">{</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">ebx</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">ecx</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">edx</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">esi</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">edi</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">ebp</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">eax</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">xds</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">xes</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">xfs</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">xgs</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">orig_eax</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">eip</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">xcs</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">eflags</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">esp</span><span class="p">;</span>
  <span class="kt">long</span> <span class="kt">int</span> <span class="n">xss</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p><strong>Notes</strong></p>

<p>The structure contains an <em>orig_eax</em> which contains in a syscall the number of the syscall, this can be used in the entry or the exit of a syscall to know the syscall number.
In Linux to search for the <strong>thread-local-storage (TLS)</strong> we must use the register <em>%gs</em> in 32 bits, and <em>%fs</em> in 64 bits.</p>

<h2 id="implementing-a-simple-debugger">Implementing a simple Debugger</h2>

<p>Complete code is in <em>ptrace_debugger.c</em>, we’ll see here the most important parts of the equation.</p>

<p>This code only works on binaries of 64 bits for Intel, and compiled as executables, so no code in the form of PIC or PIE is found (all the virtual addresses in the segments are absolute addresses, not relative virtual addresses). So the first part of the program just retrieves the program name and a function to set a breakpoint:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">((</span><span class="n">h</span><span class="p">.</span><span class="n">exec</span> <span class="o">=</span> <span class="n">strdup</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"executable strdup"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">h</span><span class="p">.</span><span class="n">exec</span><span class="p">;</span>
<span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>

<span class="k">if</span> <span class="p">((</span><span class="n">h</span><span class="p">.</span><span class="n">symname</span> <span class="o">=</span> <span class="n">strdup</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"symname strdup"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>All the data is stored in a structure developed for the program.</p>

<p>Then, file is read into a buffer and parsed with ELF structures, the only part we’ll see from here will be the check done to the binary in order to debug it or not. The first check is done to know if is a 64 bit binary:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">ehdr</span><span class="o">-&gt;</span><span class="n">e_machine</span> <span class="o">!=</span> <span class="n">EM_IA_64</span> <span class="o">&amp;&amp;</span> <span class="n">h</span><span class="p">.</span><span class="n">ehdr</span><span class="o">-&gt;</span><span class="n">e_machine</span> <span class="o">!=</span> <span class="n">EM_X86_64</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Only supported x86_64 elf binaries</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Second one is to know if binary is an EXE, or other type of binary (it could be a DYN for example). Only those compiled without PIE will be allowed:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">ehdr</span><span class="o">-&gt;</span><span class="n">e_type</span> <span class="o">!=</span> <span class="n">ET_EXEC</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"%s is not an ELF executable</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">exec</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally, we will check for symbol strings, and sections (in order to retrieve symbols), this is done to retrieve the address of the function we gave as parameter:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">ehdr</span><span class="o">-&gt;</span><span class="n">e_shstrndx</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">h</span><span class="p">.</span><span class="n">ehdr</span><span class="o">-&gt;</span><span class="n">e_shoff</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">h</span><span class="p">.</span><span class="n">ehdr</span><span class="o">-&gt;</span><span class="n">e_shnum</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Section header table not found</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">if</span> <span class="p">((</span><span class="n">h</span><span class="p">.</span><span class="n">symaddr</span> <span class="o">=</span> <span class="n">lookup_symbol</span><span class="p">(</span><span class="o">&amp;</span><span class="n">h</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">symname</span><span class="p">))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Unable to find symbol: %s not found in executable</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">symname</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>How to implement tracer and tracee</strong></p>

<p>Two different implementations can be done to create both tracer and tracee, both implementations start by the same code, create a child process, this can be done using the syscall <em>fork</em>, syscall creates a child process as a copy of the parent from the beginning of the code to that moment, for child process it returns a value 0, and for parent process return other value greater than 0, which represent the pid of child process.</p>

<ul>
  <li>Unusual implementation: in this implementation the parent process is the tracee, and the child process is the tracer. Parent process can do the next:</li>
</ul>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">prctl</span><span class="p">(</span><span class="n">PR_SET_PTRACER</span><span class="p">,</span> <span class="n">child_pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">sleep</span><span class="p">(</span><span class="n">X</span><span class="p">);</span>
</code></pre></div></div>

<p>So in this case, the parent process tells specifically that its child process can trace it, and sleep some time until child process attach to it.</p>

<p>The child process, must receive the parent process PID in order to call <em>PTRACE_ATTACH</em>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ptrace(PTRACE_ATTACH, parent_process, 0x0, 0x0);
</code></pre></div></div>

<p>This will not be in any case, the way that we will implement it is the next.</p>

<ul>
  <li>Implementation we will use: in this case, is the most common way for the implementation, the parent process will trace the child process. The child process will execute <em>ptrace</em> to indicate that it will be traced by parent process, and parent process will wait for child process.</li>
</ul>

<p>First of all create the process with <em>fork</em>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">((</span><span class="n">pid</span> <span class="o">=</span> <span class="n">fork</span><span class="p">())</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"fork"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Then we will have the check for the child process and the execution of the binary given as argument:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">// child process</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_TRACEME</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">// ptrace own </span>
    <span class="c1">// process (will be catched by parent process)</span>
    <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_TRACEME"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">execve</span><span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">exec</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">envp</span><span class="p">);</span> <span class="c1">// execute new process, </span>
    <span class="c1">// never return (this is like creating a process </span>
    <span class="c1">// suspended in windows)</span>
    <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>That code represent all that child process will do in the binary.</p>

<p>Now parent process will wait for child process, nothing more.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">status</span><span class="p">);</span>
</code></pre></div></div>

<p>As we gave as input one of the functions, we will set a breakpoint on that function, previously we obtained the address of the function through the binary symbols, the process to set a breakpoint is to read the address where we gonna set the breakpoint so we will have the original byte to restore it later, and we will set the trap byte. A software breakpoint is implemented using the byte <em>0xCC</em> once the program is gonna execute an instruction with this byte (instruction <em>int 3</em>) it will generate an exception, that exception will be catched by parent process (and we should know that it has been generated in the address of the breakpoint).</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// read address where to write breakpoint</span>
<span class="k">if</span> <span class="p">((</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)(</span><span class="n">orig</span> <span class="o">=</span> <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKTEXT</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> 
<span class="n">h</span><span class="p">.</span><span class="n">symaddr</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_PEEKTEXT"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// set software interruption</span>
<span class="n">trap</span> <span class="o">=</span> <span class="p">(</span><span class="n">orig</span> <span class="o">&amp;</span> <span class="o">~</span><span class="mh">0xff</span><span class="p">)</span> <span class="o">|</span> <span class="mh">0xcc</span><span class="p">;</span>

<span class="c1">// write instruction with breakpoint</span>
<span class="c1">// again into same address</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_POKETEXT</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">symaddr</span><span class="p">,</span> <span class="n">trap</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_POKETEXT"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Once with breakpoint set, and in order to continue process execution we will call again ptrace and we will wait for a new event:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_CONT"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">status</span><span class="p">);</span>
</code></pre></div></div>

<p>The child process will continue, and in the moment that the chosen function is executed, the breakpoint will halt the process and will wake up the parent process from the wait. This will return in the status the reason, we can check the reason with different macros, in here we will use <em>WIFSTOPPED</em> to check if child is stopped, and with <em>WSTOPSIG</em> we will check the stop status, the reason should be <strong>SIGTRAP</strong>.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">WIFSTOPPED</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGTRAP</span><span class="p">)</span>
<span class="p">{</span>
</code></pre></div></div>

<p>We can now get the register values using one of the previous structures depending on the architecture:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_GETREGS"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Once the breakpoint has halt the program, we have to follow various steps in order to:</p>

<ul>
  <li>recover the original byte from the instruction.</li>
  <li>fix the program counter to point again to the original instruction.</li>
  <li>execute only that instruction.</li>
  <li>set breakpoint again.</li>
  <li>continue the execution.</li>
</ul>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// write the original byte again back to the address</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_POKETEXT</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">symaddr</span><span class="p">,</span> <span class="n">orig</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_POKETEXT"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// fix the program counter, so point again to the instrucction</span>
<span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rip</span> <span class="o">=</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rip</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>

<span class="c1">// Set the values back to the process</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_SETREGS"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// Execute only one instrucction (the one fixed)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_SINGLESTEP</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_SINGLESTEP"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// wait for single step</span>
<span class="n">wait</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>

<span class="c1">// restore software breakpoint byte</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_POKETEXT</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">symaddr</span><span class="p">,</span> <span class="n">trap</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_POKETEXT"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally we should jump to the <em>PTRACE_CONT</em> <em>ptrace</em> call.</p>

<h2 id="implementing-an-attacher-debugger">Implementing an attacher debugger</h2>

<p>In some cases we do want to attach to an already running process. In that case, we need to get the pid of the process we want to attach to. This time we have the code in <em>ptrace_attacher.c</em>. The code is similar to the previous one, but this time we will need code to get the pid, and also to get the path of the binary in order to parse it and detect if it’s an EXE file of 64 bits.</p>

<p>So this time, we will have a switch statement in order to detect if the user is giving a pid or exe file (as it can debug both this program), and also to get the function name. To do that, we will use the <em>getopt</em> function:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="p">((</span><span class="n">c</span> <span class="o">=</span> <span class="n">getopt</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">,</span> <span class="s">"p:e:f:"</span><span class="p">))</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">switch</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
    <span class="p">{</span>
    <span class="k">case</span> <span class="sc">'p'</span><span class="p">:</span>
        <span class="n">pid</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">optarg</span><span class="p">);</span>
        <span class="n">h</span><span class="p">.</span><span class="n">exec</span> <span class="o">=</span> <span class="n">get_exe_name</span><span class="p">(</span><span class="n">pid</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">exec</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">printf</span><span class="p">(</span><span class="s">"Unable to retrieve executable path for pid: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
            <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="n">mode</span> <span class="o">=</span> <span class="n">PID_MODE</span><span class="p">;</span>
        <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="sc">'e'</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">h</span><span class="p">.</span><span class="n">exec</span> <span class="o">=</span> <span class="n">strdup</span><span class="p">(</span><span class="n">optarg</span><span class="p">))</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">perror</span><span class="p">(</span><span class="s">"strdup"</span><span class="p">);</span>
            <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="n">mode</span> <span class="o">=</span> <span class="n">EXE_MODE</span><span class="p">;</span>
        <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="sc">'f'</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">((</span><span class="n">h</span><span class="p">.</span><span class="n">symname</span> <span class="o">=</span> <span class="n">strdup</span><span class="p">(</span><span class="n">optarg</span><span class="p">))</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">perror</span><span class="p">(</span><span class="s">"strdup"</span><span class="p">);</span>
            <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">break</span><span class="p">;</span>
    <span class="nl">default:</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Unknown option</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>If pid is given instead of exe, the next code is executed in order to retrieve the exe path from the command line. This is possible in Linux thanks to the path */proc/<pid>/cmdline*, this would be the code of *get_exe_name*:</pid></p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span><span class="o">*</span>
<span class="nf">get_exe_name</span><span class="p">(</span><span class="kt">int</span> <span class="n">pid</span><span class="p">)</span>
<span class="p">{</span>
	<span class="kt">char</span> <span class="n">cmdline</span><span class="p">[</span><span class="mi">255</span><span class="p">],</span> <span class="n">path</span><span class="p">[</span><span class="mi">512</span><span class="p">],</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
	<span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
	<span class="n">snprintf</span><span class="p">(</span><span class="n">cmdline</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="s">"/proc/%d/cmdline"</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>

	<span class="k">if</span> <span class="p">((</span><span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="n">cmdline</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
	<span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Error opening file %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">cmdline</span><span class="p">);</span>
		<span class="n">perror</span><span class="p">(</span><span class="s">"open"</span><span class="p">);</span>
		<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="k">if</span> <span class="p">(</span><span class="n">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="mi">512</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">perror</span><span class="p">(</span><span class="s">"read"</span><span class="p">);</span>
		<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="k">if</span> <span class="p">((</span><span class="n">p</span> <span class="o">=</span> <span class="n">strdup</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">perror</span><span class="p">(</span><span class="s">"strdup"</span><span class="p">);</span>
		<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As we will attach to the program, we will set a handler for keyboard codes as <em>CTRL+C</em>, this handler is set with a call to the function <strong>signal</strong> giving as first parameter the signal to handle (in this case <strong>SIGINT</strong>) and as second parameter the function. In this function what we would do is to <em>dettach</em> from the traced process:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> 
<span class="nf">sighandler</span><span class="p">(</span><span class="kt">int</span> <span class="n">sig</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">printf</span><span class="p">(</span><span class="s">"Caught SIGINT: Detaching from %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">global_pid</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_DETACH</span><span class="p">,</span> <span class="n">global_pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">errno</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_DETACH"</span><span class="p">);</span>
		<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Once we obtain the path to the binary, the process is pretty similar to the previous one, we have to parse the binary, and obtain the address of the function from the symbol table of the binary, it could be that no symbol table is present, so execution could not be possible as in this case we rely on the symbols.</p>

<p>Next step will be easier than in previous case, so in previous debugger we had to create another process to trace it, this time we have to attach to the remote process by pid:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// attach to process 'pid'</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_ATTACH</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_ATTACH"</span><span class="p">);</span>
    <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// finally wait for the other process to stop</span>
<span class="n">wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">status</span><span class="p">);</span>
</code></pre></div></div>

<p>The next steps would be exactly the same than in the debugger, as the only part a little bit different is the use of <strong>PTRACE_ATTACH</strong> instead of using the <strong>PTRACE_TRACEME</strong> in the child process.</p>

<h2 id="useful-functions">Useful Functions</h2>

<h3 id="read-function">Read Function</h3>

<p>Due to the fact that the <strong>ptrace</strong> call only reads in words with <strong>PTRACE_PEEKDATA</strong>, so in 32 bits we should for example read in blocks of 4 bytes, in case that we need to read an unaligned size of bytes, we can use the next function:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">long</span> <span class="o">*</span> <span class="nf">read_data_from_memory</span><span class="p">(</span><span class="n">pid_t</span> <span class="n">pid</span><span class="p">,</span><span class="kt">long</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span><span class="kt">long</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span><span class="kt">size_t</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">size_t</span> <span class="n">size_cpy</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">read_value</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">last_value</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">remainder</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">mask_byte</span><span class="p">;</span>
  
  <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size_cpy</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// read from remote process</span>
    <span class="n">read_value</span> <span class="o">=</span> <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span><span class="n">pid</span><span class="p">,</span><span class="n">addr</span><span class="p">,</span><span class="mh">0x0</span><span class="p">);</span>
    <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">read_value</span><span class="p">;</span>
    <span class="n">addr</span> <span class="o">=</span> <span class="n">addr</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">buffer</span> <span class="o">=</span> <span class="n">buffer</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/* If size is not aligned to long (4)
    read the last part as byte, 2 bytes 
    or 3 bytes */</span>

  <span class="n">remainder</span> <span class="o">=</span> <span class="n">size</span> <span class="o">%</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mh">0x1</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">mask_byte</span> <span class="o">=</span> <span class="mh">0xff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mh">0x2</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">mask_byte</span> <span class="o">=</span> <span class="mh">0xffff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mh">0x3</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">mask_byte</span> <span class="o">=</span> <span class="mh">0xffffff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">!=</span> <span class="mh">0x0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">last_value</span> <span class="o">=</span> <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span><span class="n">pid</span><span class="p">,</span><span class="n">addr</span><span class="p">,</span> <span class="mh">0x0</span><span class="p">);</span>
    <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="o">*</span><span class="n">buffer</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">mask_byte</span> <span class="o">|</span> <span class="n">last_value</span> <span class="o">&amp;</span> <span class="n">mask_byte</span><span class="p">;</span>
  <span class="p">}</span>
  
  <span class="k">return</span> <span class="n">remainder</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="write-function">Write Function</h3>

<p>The same happen with the Write function so we have to go in rounds of 4 bytes (size of long), instead of using <strong>PTRACE_PEEKDATA</strong> to retrieve data (it will be used at the end), we will use <strong>PTRACE_POKEDATA</strong>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">write_in_memory</span><span class="p">(</span><span class="n">pid_t</span> <span class="n">current_pid</span><span class="p">,</span><span class="kt">long</span> <span class="o">*</span><span class="n">address</span><span class="p">,</span><span class="kt">void</span> <span class="o">**</span><span class="n">buffer</span><span class="p">,</span><span class="kt">size_t</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">long</span> <span class="n">last_value</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">size_cpy</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">remainder</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">mask</span><span class="p">;</span>
  
  <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size_cpy</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span><span class="n">current_pid</span><span class="p">,</span><span class="n">address</span><span class="p">,</span><span class="o">*</span><span class="n">buffer</span><span class="p">);</span>
    <span class="n">address</span> <span class="o">=</span> <span class="n">address</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">buffer</span> <span class="o">=</span> <span class="n">buffer</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>


  <span class="n">remainder</span> <span class="o">=</span> <span class="n">size</span> <span class="o">%</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">mask</span> <span class="o">=</span> <span class="mh">0xff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">mask</span> <span class="o">=</span> <span class="mh">0xffff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">mask</span> <span class="o">=</span> <span class="mh">0xffffff</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">last_value</span> <span class="o">=</span> <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span><span class="n">current_pid</span><span class="p">,</span><span class="n">address</span><span class="p">,</span> <span class="mh">0x0</span><span class="p">);</span>
    <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span><span class="n">current_pid</span><span class="p">,</span><span class="n">address</span><span class="p">,</span>
                     <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">uint</span><span class="p">)</span><span class="o">*</span><span class="n">buffer</span> <span class="o">&amp;</span> <span class="n">mask</span> <span class="o">|</span> <span class="o">~</span><span class="n">mask</span> <span class="o">&amp;</span> <span class="n">last_value</span><span class="p">));</span>
  <span class="p">}</span>
  
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="avoid-tracing-from-other-programs">Avoid Tracing From Other Programs</h3>

<p>In the same way that <strong>ptrace</strong> can be used to trace/debug a program and get its state while running, it’s possible to trick <strong>ptrace</strong> to avoid other processes to execute ptrace on a given process. So if we call <strong>ptrace</strong> with <strong>PTRACE_ATTACH</strong> giving as pid our own pid, we will set our own process as the tracer.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">current_pid</span> <span class="o">=</span> <span class="n">getpid</span><span class="p">();</span>

<span class="n">ptrace_output</span> <span class="o">=</span> <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_ATTACH</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="mh">0x0</span><span class="p">,</span> <span class="mh">0x0</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="n">ptrace_output</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">puts</span><span class="p">(</span><span class="s">"Detected a tracer already attached, killing process</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">kill</span><span class="p">(</span><span class="n">current_pid</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Also, in case we want to detect if a tracer is already attached to us, we can get its pid from one of the files in */proc/<our_pid>/status*, checking line by line, we will find one that start by *"TracerPid"*, reading that line and extracting the value we will get if there's no process tracing us (0) or if there's one process tracing us (pid of tracert):</our_pid></p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="cp">#define MAX_LEN 256
</span>
<span class="kt">int</span>
<span class="nf">GetTracerPidValue</span><span class="p">(</span><span class="n">pid_t</span> <span class="n">current_pid</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">proc_status</span> <span class="o">=</span> <span class="s">"/proc/%d/status"</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">tracerpid</span> <span class="o">=</span> <span class="s">"TracerPid:"</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">tracerpid_value</span> <span class="o">=</span> <span class="s">"TracerPid: %d"</span><span class="p">;</span>

    <span class="kt">char</span> <span class="n">proc_pid_status</span><span class="p">[</span><span class="n">MAX_LEN</span><span class="p">];</span>
    <span class="kt">FILE</span> <span class="o">*</span><span class="n">fd</span><span class="p">;</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">line_buf</span><span class="p">;</span>
    <span class="kt">size_t</span> <span class="n">line_buf_size</span><span class="p">;</span>
    <span class="kt">ssize_t</span> <span class="n">line_size</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">tracerpid_found</span><span class="p">;</span>
    <span class="kt">size_t</span> <span class="n">tracerpid_len</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">tracerpid_value_int</span><span class="p">;</span>

    <span class="n">memset</span><span class="p">(</span><span class="n">proc_pid_status</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">MAX_LEN</span><span class="p">);</span>

    <span class="n">snprintf</span><span class="p">(</span><span class="n">proc_pid_status</span><span class="p">,</span> <span class="n">MAX_LEN</span><span class="p">,</span> <span class="n">proc_status</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">);</span>
    <span class="n">fd</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">proc_pid_status</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>

    <span class="n">line_buf</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">line_buf_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">tracerpid_found</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">do</span>
    <span class="p">{</span>
        <span class="n">line_size</span> <span class="o">=</span> <span class="n">getline</span><span class="p">(</span><span class="o">&amp;</span><span class="n">line_buf</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">line_buf_size</span><span class="p">,</span> <span class="n">fd</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">line_size</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">free</span><span class="p">(</span><span class="n">line_buf</span><span class="p">);</span>
            <span class="n">fclose</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
            <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">tracerpid_len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">tracerpid</span><span class="p">);</span>
        <span class="n">tracerpid_found</span> <span class="o">=</span> <span class="n">memcmp</span><span class="p">(</span><span class="n">tracerpid</span><span class="p">,</span> <span class="n">line_buf</span><span class="p">,</span> <span class="n">tracerpid_len</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">tracerpid_found</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">sscanf</span><span class="p">(</span><span class="n">line_buf</span><span class="p">,</span> <span class="n">tracerpid_value</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">tracerpid_value_int</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">line_buf</span><span class="p">);</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">tracerpid_value_int</span><span class="p">;</span>
<span class="p">}</span>


<span class="kt">int</span>
<span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">tracerpid</span> <span class="o">=</span> <span class="n">GetTracerPidValue</span><span class="p">(</span><span class="n">getpid</span><span class="p">());</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="n">tracerpid</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Debugger detected, debugger's pid %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">tracerpid</span><span class="p">);</span>
        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"No debugger detected, all fine</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="managing-syscalls">Managing Syscalls</h3>

<p>Whenever you want to manage the syscalls in a program you’re tracing, we saw that it’s possible to stop in these syscalls using the flag <strong>PTRACE_SYSCALL</strong> in the <strong>ptrace</strong> function, this works similar to <strong>PTRACE_CONT</strong> but when a syscall is executed this will stop at the beginning of the syscall, and with another <strong>PTRACE_SYSCALL</strong> the program will stop at the end of the syscall.</p>

<p>Due to the fact that when a syscall is executed, the registers are modified, we need some way in order to know which syscall is going to be executed, for that reason in the structures of registers, we have an specific one with this number, if we know from assembly programming, the syscall number is set in <em>eax</em> or <em>rax</em> depending on the architecture, well, in the structures we have a field like <em>orig_eax</em> or <em>orig_rax</em>, these value holds the syscall number. Finally, once a syscall has finished we will have the return value in <em>eax</em> or <em>rax</em>.</p>

<p>To handle the syscall, it will be the same method than handling a breakpoint, we will have a <strong>SIGSTOP</strong>, and the reason will be a <strong>SIGTRAP</strong>. If we have a list of breakpoints, we should retrieve the value from the program counter (<em>eip</em> or <em>rip</em>) in order to check if that value - 1 (because the program counter holds the next instruction) is one of our breakpoint addresses. Also other way would be to read the program counter value - 1 memory and check if it contains a <em>0xCC</em> (software breakpoint), in that case handle the breakpoint as we saw previously and nothing more.</p>

<p>In order to know if we are at the beginning of a syscall or at the end, we can just use a “boolean” value with 1 and 0, these would be an example:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">WIFSTOPPED</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGTRAP</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// get registers from program</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_GETREGS"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rip</span> <span class="o">!=</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">symaddr</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">is_entry</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">printf</span><span class="p">(</span><span class="s">"Stop in a syscall, number of syscall: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">orig_rax</span><span class="p">);</span>
            <span class="n">is_entry</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span>
        <span class="p">{</span>
            <span class="n">printf</span><span class="p">(</span><span class="s">"End of syscall, returns: %016x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rax</span><span class="p">);</span>
            <span class="n">is_entry</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>If you remember in <em>h.symaddr</em> we had the address of the function where we set the breakpoint, this is just a simple way to manage the syscall.</p>

<p><strong>How to avoid the execution of a syscall</strong></p>

<p>As written by <a href="https://nullprogram.com/blog/2018/06/23/">nullprogram</a> we can block the execution of the syscall, setting the <em>orig_eax</em> or <em>orig_rax</em> value to <em>-1</em> as the syscall has not been executed yet at the entry of the syscall, finally, once the syscall finish, we just set in <em>eax</em> or <em>rax</em> the value <em>-EPERM</em> so the operation is not permitted:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
    <span class="cm">/* Enter next system call */</span>
    <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_SYSCALL</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">waitpid</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="k">struct</span> <span class="n">user_regs_struct</span> <span class="n">regs</span><span class="p">;</span>
    <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>

    <span class="cm">/* Is this system call permitted? */</span>
    <span class="kt">int</span> <span class="n">blocked</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">is_syscall_blocked</span><span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">orig_rax</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">blocked</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="n">regs</span><span class="p">.</span><span class="n">orig_rax</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="c1">// set to invalid syscall</span>
        <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="cm">/* Run system call and stop on exit */</span>
    <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_SYSCALL</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">waitpid</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">blocked</span><span class="p">)</span> <span class="p">{</span>
        <span class="cm">/* errno = EPERM */</span>
        <span class="n">regs</span><span class="p">.</span><span class="n">rax</span> <span class="o">=</span> <span class="o">-</span><span class="n">EPERM</span><span class="p">;</span> <span class="c1">// Operation not permitted</span>
        <span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In the previous code, we would check for a given syscall if it appears in a blacklist. In the moment before returning we can return another value if we want to emulate for example some behavior.</p>

<h3 id="managing-exceptions">Managing Exceptions</h3>

<p>With ptrace we can also manage exceptions as we did with the breakpoints and the syscalls, to do that we will have to check for a stop reason equals to <strong>SIGSEGV</strong>, inside of that code, we can get a structure of the exception with <strong>PTRACE_GETSIGINFO</strong>, in here we can get the address where the exception happened, reason, and so on. Let’s going to see an example of code:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">WIFSTOPPED</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">status</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGSEGV</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">siginfo_t</span> <span class="n">siginfo</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_GETSIGINFO</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">siginfo</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_GETSIGINFO"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// get registers from program</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"PTRACE_GETREGS"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
    
    
    <span class="n">printf</span><span class="p">(</span><span class="s">"siginfo.si_addr: 0x%08lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">siginfo</span><span class="p">.</span><span class="n">si_addr</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Exception in address: 0x%lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rip</span><span class="p">);</span>

    <span class="n">printf</span><span class="p">(</span><span class="s">"%%rcx: %016x</span><span class="se">\t</span><span class="s">%%rdx: %016x</span><span class="se">\t</span><span class="s">%%rbx: %016x</span><span class="se">\n</span><span class="s">"</span>
                <span class="s">"%%rax: %016x</span><span class="se">\t</span><span class="s">%%rdi: %016x</span><span class="se">\t</span><span class="s">%%rsi: %016x</span><span class="se">\n</span><span class="s">"</span>
                <span class="s">"%%r8:  %016x</span><span class="se">\t</span><span class="s">%%r9:  %016x</span><span class="se">\t</span><span class="s">%%r10: %016x</span><span class="se">\n</span><span class="s">"</span>
                <span class="s">"%%r11: %016x</span><span class="se">\t</span><span class="s">%%r12: %016x</span><span class="se">\t</span><span class="s">%%r13: %016x</span><span class="se">\n</span><span class="s">"</span>
                <span class="s">"%%r14: %016x</span><span class="se">\t</span><span class="s">%%r15: %016x</span><span class="se">\t</span><span class="s">%%rsp: %016x</span><span class="se">\n</span><span class="s">"</span>
                <span class="s">"%%rbp: %016x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
                <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rcx</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rdx</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rbx</span><span class="p">,</span>
                <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rax</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rdi</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rsi</span><span class="p">,</span>
                <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r8</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r9</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r10</span><span class="p">,</span>
                <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r11</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r12</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r13</span><span class="p">,</span>
                <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r14</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">r15</span><span class="p">,</span> <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rsp</span><span class="p">,</span>
                <span class="n">h</span><span class="p">.</span><span class="n">pt_reg</span><span class="p">.</span><span class="n">rbp</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="appendix">Appendix</h1>

<h2 id="flare-on-challenge-code">Flare-on challenge code</h2>

<p>Next is a code from a Flare-on challenge from a few years ago (obtained from the decompilation using Ghidra). There were two “debuggers” implemented, next the code shows the first and the second debugger implemented</p>

<h3 id="first-debugger">First Debugger</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="c1"> // Posix header</span><span class="cp">
#include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;errno.h&gt;</span><span class="c1">  // Standard errors</span><span class="cp">
#include</span> <span class="cpf">&lt;signal.h&gt;</span><span class="c1"> // Unix signals</span><span class="cp">
#include</span> <span class="cpf">&lt;elf.h&gt;</span><span class="c1">    // ELF headers</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/wait.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/user.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/stat.h&gt;</span><span class="c1">   // file stats</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/ptrace.h&gt;</span><span class="c1"> // ptrace debugging syscall</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/mman.h&gt;</span><span class="c1">   // memory mapping</span><span class="cp">
</span>
<span class="cm">/* This function directly loads libc.so.6
   and the function ptrace, instead of relying
   on PLT/GOT.
   Call to ptrace */</span>

<span class="kt">long</span> <span class="nf">call_real_ptrace</span><span class="p">(</span><span class="n">__ptrace_request</span> <span class="n">request</span><span class="p">,</span> <span class="n">pid_t</span> <span class="n">pid</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">libc_so_6</span><span class="p">;</span>
  <span class="n">ptrace</span> <span class="o">*</span><span class="n">ptrace</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">ptrace_return</span><span class="p">;</span>

  <span class="n">libc_so_6</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">dlopen</span><span class="p">(</span><span class="s">"libc.so.6"</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
  <span class="n">ptrace</span> <span class="o">=</span> <span class="p">(</span><span class="n">ptrace</span> <span class="o">*</span><span class="p">)</span><span class="n">dlsym</span><span class="p">(</span><span class="n">libc_so_6</span><span class="p">,</span> <span class="s">"ptrace"</span><span class="p">);</span>
  <span class="n">ptrace_return</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">ptrace</span><span class="p">)(</span><span class="n">request</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
  <span class="k">return</span> <span class="n">ptrace_return</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">long</span> <span class="o">*</span><span class="nf">read_data_from_memory</span><span class="p">(</span><span class="n">pid_t</span> <span class="n">pid</span><span class="p">,</span> <span class="kt">long</span> <span class="o">*</span><span class="n">addr</span><span class="p">,</span> <span class="kt">long</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">)</span>

<span class="p">{</span>
  <span class="kt">size_t</span> <span class="n">size_cpy</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">read_value</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">last_value</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">remainder</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">mask_byte</span><span class="p">;</span>

  <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span><span class="n">i</span><span class="o">&lt;</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size_cpy</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">read_value</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
    <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">read_value</span><span class="p">;</span>
    <span class="n">addr</span> <span class="o">=</span> <span class="n">addr</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">buffer</span> <span class="o">=</span> <span class="n">buffer</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="cm">/* If size is not aligned to long (4)
                       read the last part as byte, 2 bytes or 3 bytes */</span>

  <span class="n">remainder</span> <span class="o">=</span> <span class="n">size</span> <span class="o">%</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mh">0x1</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">mask_byte</span> <span class="o">=</span> <span class="mh">0xff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mh">0x2</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">mask_byte</span> <span class="o">=</span> <span class="mh">0xffff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mh">0x3</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">mask_byte</span> <span class="o">=</span> <span class="mh">0xffffff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">!=</span> <span class="mh">0x0</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">last_value</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
    <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="o">*</span><span class="n">buffer</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">mask_byte</span> <span class="o">|</span> <span class="n">last_value</span> <span class="o">&amp;</span> <span class="n">mask_byte</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="n">remainder</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">write_in_memory</span><span class="p">(</span><span class="n">pid_t</span> <span class="n">current_pid</span><span class="p">,</span> <span class="kt">long</span> <span class="o">*</span><span class="n">address</span><span class="p">,</span> <span class="kt">void</span> <span class="o">**</span><span class="n">buffer</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">)</span>

<span class="p">{</span>
  <span class="kt">long</span> <span class="n">last_value</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">size_cpy</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">remainder</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">mask</span><span class="p">;</span>

  <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">size_cpy</span> <span class="o">=</span> <span class="n">size</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span><span class="n">i</span><span class="o">&lt;</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size_cpy</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="o">*</span><span class="n">buffer</span><span class="p">);</span>
    <span class="n">address</span> <span class="o">=</span> <span class="n">address</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">buffer</span> <span class="o">=</span> <span class="n">buffer</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="n">remainder</span> <span class="o">=</span> <span class="n">size</span> <span class="o">%</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">mask</span> <span class="o">=</span> <span class="mh">0xff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">mask</span> <span class="o">=</span> <span class="mh">0xffff</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">mask</span> <span class="o">=</span> <span class="mh">0xffffff</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">remainder</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">last_value</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
    <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span>
                     <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">uint</span><span class="p">)</span><span class="o">*</span><span class="n">buffer</span> <span class="o">&amp;</span> <span class="n">mask</span> <span class="o">|</span> <span class="o">~</span><span class="n">mask</span> <span class="o">&amp;</span> <span class="n">last_value</span><span class="p">));</span>
  <span class="p">}</span>

  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">GetTracerPidValue</span><span class="p">(</span><span class="n">__pid_t</span> <span class="n">current_pid</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">size_t</span> <span class="n">tracerpid_len</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">tracerpid_found</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">iVar1</span><span class="p">;</span>
  <span class="n">undefined4</span> <span class="o">*</span><span class="n">puVar2</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">in_GS_OFFSET</span><span class="p">;</span>
  <span class="kt">char</span> <span class="o">*</span><span class="n">line_buf</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">line_buf_size</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">tracerpid_value_int</span><span class="p">;</span>
  <span class="kt">FILE</span> <span class="o">*</span><span class="n">fd</span><span class="p">;</span>
  <span class="n">__ssize_t</span> <span class="n">line_size</span><span class="p">;</span>
  <span class="kt">char</span> <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">11</span><span class="p">];</span>
  <span class="kt">char</span> <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">14</span><span class="p">];</span>
  <span class="kt">char</span> <span class="n">proc_status</span><span class="p">[</span><span class="mi">16</span><span class="p">];</span>
  <span class="n">undefined4</span> <span class="n">proc_pid_status</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
  <span class="kt">int</span> <span class="n">COOKIE</span><span class="p">;</span>

  <span class="n">COOKIE</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">in_GS_OFFSET</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">);</span>
  <span class="n">iVar1</span> <span class="o">=</span> <span class="mh">0x40</span><span class="p">;</span>
  <span class="n">puVar2</span> <span class="o">=</span> <span class="n">proc_pid_status</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span><span class="n">iVar1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">iVar1</span> <span class="o">=</span> <span class="n">iVar1</span> <span class="o">+</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
    <span class="o">*</span><span class="n">puVar2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">puVar2</span> <span class="o">=</span> <span class="n">puVar2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'/'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'p'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'r'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'o'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'c'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'/'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'%'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'d'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'/'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'s'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'t'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'a'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'t'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">13</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'u'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">14</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'s'</span><span class="p">;</span>
  <span class="n">proc_status</span><span class="p">[</span><span class="mi">15</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'T'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'r'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'a'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'c'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'e'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'r'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'P'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'i'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'d'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="sc">':'</span><span class="p">;</span>
  <span class="n">Tracerpid</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'T'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'r'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'a'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'c'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'e'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'r'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'P'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'i'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'d'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="sc">':'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'%'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'d'</span><span class="p">;</span>
  <span class="n">Tracerpid_value</span><span class="p">[</span><span class="mi">13</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">sprintf</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">proc_pid_status</span><span class="p">,</span> <span class="n">proc_status</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">);</span>
  <span class="n">fd</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">proc_pid_status</span><span class="p">,</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">BYTE_0805695c</span><span class="p">);</span>
  <span class="n">line_buf</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">;</span>
  <span class="n">line_buf_size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">do</span>
  <span class="p">{</span>
    <span class="cm">/* This breaks on the debugger probably because
                       a TOCTOU error, the file is deleted before
                       the process can access it. */</span>
    <span class="n">line_size</span> <span class="o">=</span> <span class="n">getline</span><span class="p">(</span><span class="o">&amp;</span><span class="n">line_buf</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">line_buf_size</span><span class="p">,</span> <span class="n">fd</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">line_size</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="n">free</span><span class="p">(</span><span class="n">line_buf</span><span class="p">);</span>
      <span class="n">fclose</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
      <span class="n">tracerpid_value_int</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="k">goto</span> <span class="n">LAB_0804bfd7</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">tracerpid_len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">Tracerpid</span><span class="p">);</span>
    <span class="n">tracerpid_found</span> <span class="o">=</span> <span class="n">memcmp</span><span class="p">(</span><span class="n">Tracerpid</span><span class="p">,</span> <span class="n">line_buf</span><span class="p">,</span> <span class="n">tracerpid_len</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">tracerpid_found</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">);</span>
  <span class="n">__isoc99_sscanf</span><span class="p">(</span><span class="n">line_buf</span><span class="p">,</span> <span class="n">Tracerpid_value</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">tracerpid_value_int</span><span class="p">);</span>
  <span class="n">free</span><span class="p">(</span><span class="n">line_buf</span><span class="p">);</span>
  <span class="n">fclose</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="nl">LAB_0804bfd7:</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">COOKIE</span> <span class="o">!=</span> <span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">in_GS_OFFSET</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">))</span>
  <span class="p">{</span>
    <span class="cm">/* WARNING: Subroutine does not return */</span>
    <span class="n">__stack_chk_fail</span><span class="p">();</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">tracerpid_value_int</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */</span>

<span class="kt">void</span> <span class="nf">first_debugger</span><span class="p">(</span><span class="n">__pid_t</span> <span class="n">parent_process</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">long</span> <span class="n">ptrace_Return</span><span class="p">;</span>
  <span class="n">__pid_t</span> <span class="n">_Var1</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">value_0x9e3779b9</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">sVar2</span><span class="p">;</span>
  <span class="kt">char</span> <span class="o">*</span><span class="n">pcVar3</span><span class="p">;</span>
  <span class="kt">char</span> <span class="n">chmod_pathname</span><span class="p">[</span><span class="mi">248</span><span class="p">];</span>
  <span class="n">uint</span> <span class="n">wstatus</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">crc64_first_dword</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">crc64_second_dword</span><span class="p">;</span>
  <span class="n">byte</span> <span class="n">file_to_truncate</span><span class="p">[</span><span class="mi">16000</span><span class="p">];</span>
  <span class="n">user_regs_struct32</span> <span class="n">regs</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">wstatus2</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">check_WSTOPPED</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">check_SIGSTOP</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">check_SIGTRAP</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">check_SIGILL</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">check_SIGSEGV</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">local_74</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">local_70</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">local_6c</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">wstatus_cpy</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">local_64</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">parameter_2_value_incremented</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">parameter_2</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">parameter_1</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">address_exception</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">stack_esp</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">**</span><span class="n">buffer_to_write</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">len_buffer_to_write</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">**</span><span class="n">string_decrypted</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">obfuscated_syscall</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">bytes_from_syscall</span><span class="p">;</span>
  <span class="kt">int</span> <span class="o">*</span><span class="n">paddress_to_write</span><span class="p">;</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">exit_status</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">tracerpid_value</span><span class="p">;</span>
  <span class="n">code</span> <span class="o">*</span><span class="n">p_zero</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">index_different</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">incremental_value</span><span class="p">;</span>

  <span class="n">p_zero</span> <span class="o">=</span> <span class="p">(</span><span class="n">code</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">;</span>
  <span class="cm">/* try to attach to parent
       if ptrace_Return == -1: parent has died already or gdb is attached to parent.
       else: parent is attacheable */</span>
  <span class="n">ptrace_Return</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_ATTACH</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">ptrace_Return</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="cm">/* No tracing allowed!!!
           Check if parent process has a PID
           in TracerPid. */</span>
    <span class="n">tracerpid_value</span> <span class="o">=</span> <span class="n">GetTracerPidValue</span><span class="p">(</span><span class="n">parent_process</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tracerpid_value</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="cm">/* No tracer found, error, abort mission */</span>
      <span class="n">puts</span><span class="p">(</span><span class="s">"OOPSIE WOOPSIE!! Uwu We made a mistaky wakey!!!!"</span><span class="p">);</span>
      <span class="n">kill</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span>
    <span class="p">{</span>
      <span class="cm">/* Try to attach to debugger of parent process */</span>
      <span class="n">ptrace_Return</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_ATTACH</span><span class="p">,</span> <span class="n">tracerpid_value</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">ptrace_Return</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
      <span class="p">{</span>
        <span class="cm">/* Kill my parent debugger and myself */</span>
        <span class="n">kill</span><span class="p">(</span><span class="n">tracerpid_value</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
        <span class="n">kill</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="k">else</span>
      <span class="p">{</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">_Var1</span> <span class="o">=</span> <span class="n">waitpid</span><span class="p">(</span><span class="n">tracerpid_value</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">wstatus</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">_Var1</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
        <span class="p">{</span>
          <span class="n">wstatus_cpy</span> <span class="o">=</span> <span class="n">wstatus</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WIFSTOPPED</span><span class="p">(</span><span class="n">wstatus</span><span class="p">))</span>
          <span class="p">{</span>
            <span class="n">local_64</span> <span class="o">=</span> <span class="n">wstatus</span><span class="p">;</span>
            <span class="n">exit_status</span> <span class="o">=</span> <span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">((</span><span class="n">exit_status</span> <span class="o">==</span> <span class="n">SIGSTOP</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">exit_status</span> <span class="o">==</span> <span class="n">SIGCHLD</span><span class="p">))</span>
            <span class="p">{</span>
              <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">tracerpid_value</span><span class="p">,</span> <span class="mh">0x0</span><span class="p">,</span> <span class="mh">0x0</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
              <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">tracerpid_value</span><span class="p">,</span> <span class="mh">0x0</span><span class="p">,</span> <span class="n">exit_status</span><span class="p">);</span>
            <span class="p">}</span>
          <span class="p">}</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">else</span>
  <span class="p">{</span>
    <span class="cm">/* Set breakpoint after waitpid and continue before fork
           so it's possible to attach to parent and waitpid */</span>
    <span class="n">_Var1</span> <span class="o">=</span> <span class="n">waitpid</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">wstatus2</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">_Var1</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="cm">/* set first 4 bytes of compare_false_flag to
               0f 0b 00 00, in parent process */</span>
      <span class="n">ptrace_Return</span> <span class="o">=</span>
          <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="n">compare_false_flag</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0xb0f</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">ptrace_Return</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
      <span class="p">{</span>
        <span class="cm">/* WARNING: Subroutine does not return */</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="cm">/* set killl_process_call_function as handler for signal 0xe */</span>
      <span class="n">signal</span><span class="p">(</span><span class="n">SIGALRM</span><span class="p">,</span> <span class="n">kill_process_call_function</span><span class="p">);</span>
      <span class="n">_Var1</span> <span class="o">=</span> <span class="n">getpid</span><span class="p">();</span>
      <span class="n">create_third_process</span><span class="p">(</span><span class="n">_Var1</span><span class="p">);</span>
      <span class="n">paddress_to_write</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">address_to_write</span><span class="p">;</span>
      <span class="n">_address_to_write</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="cm">/* macOS anti-debug technique
               
            (https://cardaci.xyz/blog/2018/02/12/a-macos-anti-debug-technique-using-ptrace/)
                */</span>
      <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PT_DENY_ATTACH</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
      <span class="k">while</span> <span class="p">(</span><span class="n">_Var1</span> <span class="o">=</span> <span class="n">waitpid</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">wstatus2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">_Var1</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
      <span class="p">{</span>
        <span class="cm">/* analyze WSTOPPED reasons, check ptrace documentation
                   analysis of SIGSTOP, SIGTRAP, and so on */</span>
        <span class="n">check_WSTOPPED</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">WIFSTOPPED</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">))</span>
        <span class="p">{</span>
          <span class="n">check_SIGSTOP</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGSTOP</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="cm">/* SIGSTOP send, someone trying to attach parent process, deny attach */</span>
            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PT_DENY_ATTACH</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
          <span class="p">}</span>
          <span class="n">check_SIGTRAP</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGTRAP</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="cm">/* Syscall-stop analyze the syscall */</span>
            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
            <span class="cm">/* Get first bytes from syscall address, check if
                           debugger has set a breakpoint */</span>
            <span class="n">bytes_from_syscall</span> <span class="o">=</span>
                <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">+</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">bytes_from_syscall</span> <span class="o">==</span> <span class="mh">0xffffffff</span><span class="p">)</span>
            <span class="p">{</span>
              <span class="cm">/* WARNING: Subroutine does not return */</span>
              <span class="cm">/* Wabalaba dub dub */</span>
              <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">if</span> <span class="p">((</span><span class="n">bytes_from_syscall</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">)</span> <span class="o">==</span> <span class="mh">0xcc</span><span class="p">)</span>
            <span class="p">{</span>
              <span class="cm">/* Detected breakpoint, fuck off!!! */</span>
              <span class="n">kill</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
              <span class="cm">/* WARNING: Subroutine does not return */</span>
              <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="cm">/* get an scramble the original eax (syscall number) */</span>
            <span class="n">obfuscated_syscall</span> <span class="o">=</span> <span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">orig_eax</span> <span class="o">^</span> <span class="mh">0xdeadbeef</span><span class="p">)</span> <span class="o">*</span> <span class="mh">0x1337cafe</span><span class="p">;</span>
            <span class="n">index_different</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_pivot_root</span><span class="p">)</span>
            <span class="p">{</span>
              <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ecx</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
              <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">&lt;</span> <span class="n">__NR_pivot_root</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
              <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_getpriority</span><span class="p">)</span>
                <span class="p">{</span>
                  <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">paddress_to_write</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
                  <span class="p">{</span>
                    <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="o">*</span><span class="n">paddress_to_write</span><span class="p">;</span>
                  <span class="p">}</span>
                  <span class="k">else</span>
                  <span class="p">{</span>
                    <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="o">*</span><span class="n">paddress_to_write</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">;</span>
                  <span class="p">}</span>
                  <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                  <span class="o">*</span><span class="n">paddress_to_write</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
                <span class="p">}</span>
                <span class="k">else</span>
                <span class="p">{</span>
                  <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">&lt;</span> <span class="n">__NR_getpriority</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
                  <span class="p">{</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_setpriority</span><span class="p">)</span>
                    <span class="p">{</span>
                      <span class="cm">/* if edx == 0xa4: "This string has no purpose and is merely here to waste your
                      time."
                      if edx == 0xa5: [227, 118, 105, 146, 199, 92, 232, 245, 133, 197, 77, 17, 22,
                      250, 244, 232, 0]
                      if edx = 0xaa: """
                      welcome to the land of sunshine and rainbows!
                      as a reward for getting this far in FLARE-ON, we've decided to make this one
                      soooper easy
                      
                      please enter a password friend :) 
                      " */</span>
                      <span class="n">buffer_to_write</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">decrypt_string_by_index</span><span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">edx</span><span class="p">);</span>
                      <span class="n">sVar2</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer_to_write</span><span class="p">);</span>
                      <span class="n">write_in_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">address_to_write</span><span class="p">,</span> <span class="n">buffer_to_write</span><span class="p">,</span>
                                      <span class="n">sVar2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
                      <span class="o">*</span><span class="n">paddress_to_write</span> <span class="o">=</span> <span class="o">-</span><span class="mh">0x81a52a0</span><span class="p">;</span>
                      <span class="n">free</span><span class="p">(</span><span class="n">buffer_to_write</span><span class="p">);</span>
                      <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
                      <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                    <span class="p">}</span>
                    <span class="k">else</span>
                    <span class="p">{</span>
                      <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_read</span><span class="p">)</span>
                      <span class="p">{</span>
                        <span class="cm">/* if debugger detects a call to "read" it calls
                                                   fgets to get user flag in a global variable
                                                   but what is copied to buffer of read, is a decrypted
                                                   string, then eax is set to size of the decrypted string */</span>
                        <span class="n">fgets</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="mh">0xff</span><span class="p">,</span> <span class="n">stdin</span><span class="p">);</span>
                        <span class="cm">/* decrypted = "sorry i stole your input :)" */</span>
                        <span class="n">string_decrypted</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">decrypt_string_by_index</span><span class="p">(</span><span class="mh">0xb8</span><span class="p">);</span>
                        <span class="n">_buffer_pointer</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">ecx</span><span class="p">;</span>
                        <span class="n">sVar2</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">string_decrypted</span><span class="p">);</span>
                        <span class="n">write_in_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ecx</span><span class="p">,</span> <span class="n">string_decrypted</span><span class="p">,</span> <span class="n">sVar2</span><span class="p">);</span>
                        <span class="n">sVar2</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">string_decrypted</span><span class="p">);</span>
                        <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">sVar2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
                        <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                      <span class="p">}</span>
                    <span class="p">}</span>
                  <span class="p">}</span>
                  <span class="k">else</span>
                  <span class="p">{</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_exit</span><span class="p">)</span>
                    <span class="p">{</span>
                      <span class="cm">/* set exit status to 1 */</span>
                      <span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">+</span> <span class="o">-</span><span class="mi">2</span><span class="p">;</span>
                      <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
                      <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                      <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                      <span class="cm">/* WARNING: Subroutine does not return */</span>
                      <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
                    <span class="p">}</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">_NR_mlockall</span><span class="p">)</span>
                    <span class="p">{</span>
                      <span class="n">crc64_first_dword</span> <span class="o">=</span>
                          <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span><span class="p">,</span>
                                           <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                      <span class="n">crc64_second_dword</span> <span class="o">=</span>
                          <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span> <span class="o">+</span> <span class="mi">4</span><span class="p">),</span>
                                           <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                      <span class="n">incremental_value</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
                      <span class="k">while</span> <span class="p">((</span><span class="n">crc64_first_dword</span> <span class="o">|</span> <span class="n">crc64_second_dword</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
                      <span class="p">{</span>
                        <span class="k">if</span> <span class="p">((</span><span class="n">crc64_first_dword</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
                        <span class="p">{</span>
                          <span class="n">incremental_value</span> <span class="o">=</span>
                              <span class="p">(</span><span class="o">*</span><span class="n">p_zero</span><span class="p">)(</span><span class="n">INS_INCREMENT</span><span class="p">,</span> <span class="n">incremental_value</span><span class="p">,</span> <span class="n">crc64_second_dword</span><span class="p">);</span>
                        <span class="p">}</span>
                        <span class="n">crc64_first_dword</span> <span class="o">=</span> <span class="n">crc64_first_dword</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">crc64_second_dword</span> <span class="o">&lt;&lt;</span> <span class="mh">0x1f</span><span class="p">;</span>
                        <span class="n">crc64_second_dword</span> <span class="o">=</span> <span class="n">crc64_second_dword</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">;</span>
                      <span class="p">}</span>
                      <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">incremental_value</span><span class="p">;</span>
                      <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                    <span class="p">}</span>
                    <span class="k">else</span>
                    <span class="p">{</span>
                      <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_chmod</span><span class="p">)</span>
                      <span class="p">{</span>
                        <span class="n">read_data_from_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">chmod_pathname</span><span class="p">,</span> <span class="mh">0xf8</span><span class="p">);</span>
                        <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">apply_add_ror_xor_to_values</span><span class="p">(</span><span class="n">chmod_pathname</span><span class="p">,</span> <span class="n">regs</span><span class="p">.</span><span class="n">ecx</span><span class="p">);</span>
                        <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                      <span class="p">}</span>
                    <span class="p">}</span>
                  <span class="p">}</span>
                <span class="p">}</span>
              <span class="p">}</span>
              <span class="k">else</span>
              <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_ioctl</span><span class="p">)</span>
                <span class="p">{</span>
                  <span class="k">if</span> <span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span> <span class="o">==</span> <span class="mh">0x1337</span><span class="p">)</span>
                  <span class="p">{</span>
                    <span class="cm">/* if file descriptor of ioctl == 0x1337 */</span>
                    <span class="n">buffer_to_write</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">decrypt_string_by_index</span><span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">ecx</span><span class="p">);</span>
                    <span class="n">write_in_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">address_to_write</span><span class="p">,</span> <span class="n">buffer_to_write</span><span class="p">,</span>
                                    <span class="n">regs</span><span class="p">.</span><span class="n">edx</span><span class="p">);</span>
                    <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="o">&amp;</span><span class="n">address_to_write</span><span class="p">;</span>
                    <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                  <span class="p">}</span>
                  <span class="k">else</span>
                  <span class="p">{</span>
                    <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
                    <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                  <span class="p">}</span>
                <span class="p">}</span>
                <span class="k">else</span>
                <span class="p">{</span>
                  <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">&lt;</span> <span class="n">__NR_ioctl</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
                  <span class="p">{</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_execve</span><span class="p">)</span>
                    <span class="p">{</span>
                      <span class="cm">/* execve just removes the last '\n' from the string given as
                                               flag, so it does not execute anything */</span>
                      <span class="n">buffer_to_write</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="mi">300</span><span class="p">);</span>
                      <span class="n">read_size_or_until_0xff</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span><span class="p">,</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer_to_write</span><span class="p">,</span> <span class="mi">300</span><span class="p">);</span>
                      <span class="n">len_buffer_to_write</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer_to_write</span><span class="p">);</span>
                      <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)((</span><span class="kt">int</span><span class="p">)</span><span class="n">buffer_to_write</span> <span class="o">+</span> <span class="p">(</span><span class="n">len_buffer_to_write</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span> <span class="o">==</span> <span class="sc">'\n'</span><span class="p">)</span>
                      <span class="p">{</span>
                        <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span>
                                         <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">len_buffer_to_write</span> <span class="o">+</span> <span class="n">regs</span><span class="p">.</span><span class="n">ebx</span> <span class="o">+</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                      <span class="p">}</span>
                      <span class="n">free</span><span class="p">(</span><span class="n">buffer_to_write</span><span class="p">);</span>
                    <span class="p">}</span>
                    <span class="k">else</span>
                    <span class="p">{</span>
                      <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_uname</span><span class="p">)</span>
                      <span class="p">{</span>
                        <span class="cm">/* uname set the TEA algorithm:
                                                   sum = 0xC6EF3720;
                                                   delta = 0x9e3779b9 */</span>
                        <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span><span class="p">,</span>
                                         <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">TEA_DECRYPTION_SUM</span><span class="p">);</span>
                        <span class="n">value_0x9e3779b9</span> <span class="o">=</span>
                            <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="o">*</span><span class="n">p_zero</span><span class="p">)(</span><span class="n">INS_SET_TEA_KEY_SCHEDULE_CONSTANT</span><span class="p">,</span> <span class="mh">0x1337</span><span class="p">,</span> <span class="mh">0xcafe</span><span class="p">);</span>
                        <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span> <span class="o">+</span> <span class="mi">4</span><span class="p">),</span>
                                         <span class="n">value_0x9e3779b9</span><span class="p">);</span>
                      <span class="p">}</span>
                    <span class="p">}</span>
                  <span class="p">}</span>
                  <span class="k">else</span>
                  <span class="p">{</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_truncate</span><span class="p">)</span>
                    <span class="p">{</span>
                      <span class="n">read_data_from_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer_file_to_truncate</span><span class="p">,</span>
                                            <span class="mi">40000</span><span class="p">);</span>
                      <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
                      <span class="k">while</span> <span class="p">((</span><span class="n">i</span> <span class="o">&lt;</span> <span class="mi">40000</span> <span class="o">&amp;&amp;</span>
                              <span class="p">(</span><span class="n">buffer_file_to_truncate</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span>
                               <span class="cm">/* file to truncate has been modified in a decrypt_real_flag function */</span>
                               <span class="p">)))</span>
                      <span class="p">{</span>
                        <span class="n">file_to_truncate</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">buffer_file_to_truncate</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                        <span class="k">if</span> <span class="p">((</span><span class="n">index_different</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
                            <span class="p">(</span><span class="n">file_to_truncate</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">DAT_081a5100</span><span class="p">)[</span><span class="n">i</span><span class="p">]</span>
                             <span class="cm">/* check please that file_to_truncate is different than a given array */</span>
                             <span class="cm">/* DAT_081a5100 decrypted = "4nD_0f_De4th_4nd_d3strUct1oN_4nd",
                                                           so we would have at least
                                                           w3lc0mE_t0_Th3_l4nD_0f_De4th_4nd_d3strUct1oN_4nd */</span>
                             <span class="p">))</span>
                        <span class="p">{</span>
                          <span class="n">index_different</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
                        <span class="p">}</span>
                        <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
                      <span class="p">}</span>
                      <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">p_zero</span><span class="p">)(</span><span class="n">INS_COMPARE_FLAG</span><span class="p">,</span> <span class="n">flag</span><span class="p">,</span> <span class="n">index_different</span><span class="p">);</span>
                      <span class="n">index_different</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">eax</span><span class="p">;</span>
                      <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                    <span class="p">}</span>
                    <span class="k">else</span>
                    <span class="p">{</span>
                      <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_write</span><span class="p">)</span>
                      <span class="p">{</span>
                        <span class="cm">/* Take buffer with size and call directly write for
                                                   writing to stdout */</span>
                        <span class="n">len_buffer_to_write</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">edx</span><span class="p">;</span>
                        <span class="n">buffer_to_write</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">edx</span><span class="p">);</span>
                        <span class="n">read_data_from_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">ecx</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer_to_write</span><span class="p">,</span>
                                              <span class="n">len_buffer_to_write</span><span class="p">);</span>
                        <span class="n">write</span><span class="p">(</span><span class="n">STDOUT_FILENO</span><span class="p">,</span> <span class="n">buffer_to_write</span><span class="p">,</span> <span class="n">len_buffer_to_write</span><span class="p">);</span>
                        <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">len_buffer_to_write</span><span class="p">;</span>
                        <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                        <span class="n">free</span><span class="p">(</span><span class="n">buffer_to_write</span><span class="p">);</span>
                      <span class="p">}</span>
                      <span class="k">else</span>
                      <span class="p">{</span>
                        <span class="k">if</span> <span class="p">(</span><span class="n">obfuscated_syscall</span> <span class="o">==</span> <span class="n">__NR_nice</span><span class="p">)</span>
                        <span class="p">{</span>
                          <span class="cm">/* call to nice what it really does is to
                                                       decrypt a string and write to parent
                                                       process memory */</span>
                          <span class="n">buffer_to_write</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">decrypt_string_with_struct</span><span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">ebx</span><span class="p">);</span>
                          <span class="n">sVar2</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer_to_write</span><span class="p">);</span>
                          <span class="n">write_in_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">address_to_write</span><span class="p">,</span> <span class="n">buffer_to_write</span><span class="p">,</span>
                                          <span class="n">sVar2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
                          <span class="n">free</span><span class="p">(</span><span class="n">buffer_to_write</span><span class="p">);</span>
                          <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
                          <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                        <span class="p">}</span>
                      <span class="p">}</span>
                    <span class="p">}</span>
                  <span class="p">}</span>
                <span class="p">}</span>
              <span class="p">}</span>
            <span class="p">}</span>
          <span class="p">}</span>
          <span class="n">check_SIGILL</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGILL</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="cm">/* copy flag value into parent process memory
                           and set it as a stack parameter
                           finally redirect first process to a diferent
                           method */</span>
            <span class="n">sVar2</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">flag</span><span class="p">);</span>
            <span class="n">write_in_memory</span><span class="p">(</span><span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">flag</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">flag</span><span class="p">,</span> <span class="n">sVar2</span><span class="p">);</span>
            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
            <span class="n">stack_esp</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">esp</span><span class="p">;</span>
            <span class="n">ptrace_Return</span> <span class="o">=</span>
                <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mi">4</span><span class="p">),</span> <span class="n">flag</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">ptrace_Return</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
            <span class="p">{</span>
              <span class="cm">/* WARNING: Subroutine does not return */</span>
              <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="cm">/* set eip as address to function that calls rm -rf -no-preserve-root */</span>
            <span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">=</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">function_rm_rf_no_preserve_root</span><span class="p">;</span>
            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
          <span class="p">}</span>
          <span class="n">check_SIGSEGV</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGSEGV</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
            <span class="n">address_exception</span> <span class="o">=</span>
                <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
            <span class="n">parameter_1</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mi">4</span><span class="p">),</span>
                                           <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
            <span class="n">parameter_2</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span>
                                                   <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
            <span class="n">ptrace_Return</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="n">parameter_2</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
            <span class="cm">/* take index from function FUN_0804c217 and increment it */</span>
            <span class="n">parameter_2_value_incremented</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">ptrace_Return</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
            <span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">parameter_2_value_incremented</span> <span class="o">&lt;</span> <span class="mh">0x10</span><span class="p">)</span>
            <span class="p">{</span>
              <span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">=</span> <span class="n">parameter_1</span><span class="p">;</span>
              <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="n">parameter_2</span><span class="p">,</span>
                               <span class="n">parameter_2_value_incremented</span><span class="p">);</span>
              <span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
              <span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">=</span> <span class="n">address_exception</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
          <span class="p">}</span>
          <span class="n">local_74</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGINT</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="cm">/* CTRL+C
                           0xbc = I HAVE THE CONCH DON'T INTERRUPT ME
                            */</span>
            <span class="n">pcVar3</span> <span class="o">=</span> <span class="n">decrypt_string_by_index</span><span class="p">(</span><span class="mh">0xbc</span><span class="p">);</span>
            <span class="n">puts</span><span class="p">(</span><span class="n">pcVar3</span><span class="p">);</span>
          <span class="p">}</span>
          <span class="n">local_70</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGTERM</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="n">pcVar3</span> <span class="o">=</span> <span class="n">decrypt_string_by_index</span><span class="p">(</span><span class="mh">0xa3</span><span class="p">);</span>
            <span class="n">puts</span><span class="p">(</span><span class="n">pcVar3</span><span class="p">);</span>
          <span class="p">}</span>
          <span class="n">local_6c</span> <span class="o">=</span> <span class="n">wstatus2</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus2</span><span class="p">)</span> <span class="o">==</span> <span class="n">SIGQUIT</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="cm">/* 0xbe = winners never quit */</span>
            <span class="n">pcVar3</span> <span class="o">=</span> <span class="n">decrypt_string_by_index</span><span class="p">(</span><span class="mh">0xbe</span><span class="p">);</span>
            <span class="n">puts</span><span class="p">(</span><span class="n">pcVar3</span><span class="p">);</span>
          <span class="p">}</span>
          <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PT_DENY_ATTACH</span><span class="p">,</span> <span class="n">parent_process</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="second-debugger">Second Debugger</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="c1"> // Posix header</span><span class="cp">
#include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;errno.h&gt;</span><span class="c1">  // Standard errors</span><span class="cp">
#include</span> <span class="cpf">&lt;signal.h&gt;</span><span class="c1"> // Unix signals</span><span class="cp">
#include</span> <span class="cpf">&lt;elf.h&gt;</span><span class="c1">    // ELF headers</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/wait.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/user.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/stat.h&gt;</span><span class="c1">   // file stats</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/ptrace.h&gt;</span><span class="c1"> // ptrace debugging syscall</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/mman.h&gt;</span><span class="c1">   // memory mapping</span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">second_debugger</span><span class="p">(</span><span class="n">__pid_t</span> <span class="n">current_pid</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">long</span> <span class="n">ptrace_output</span><span class="p">;</span>
    <span class="n">__pid_t</span> <span class="n">return_waitpid</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">compare_with_no_flare</span><span class="p">;</span>
    <span class="kt">char</span> <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">36</span><span class="p">];</span>
    <span class="n">user_regs_struct32</span> <span class="n">regs</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">wstatus</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">local_2c</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">local_28</span><span class="p">;</span>
    <span class="n">uint</span> <span class="n">param2</span><span class="p">;</span>
    <span class="kt">long</span> <span class="o">*</span><span class="n">param1</span><span class="p">;</span>
    <span class="kt">long</span> <span class="n">instruction</span><span class="p">;</span>
    <span class="kt">long</span> <span class="n">return_inst_addr</span><span class="p">;</span>
    <span class="kt">void</span> <span class="o">*</span><span class="n">stopsig</span><span class="p">;</span>

    <span class="n">prctl</span><span class="p">(</span><span class="n">PR_SET_DUMPABLE</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">signal</span><span class="p">(</span><span class="n">SIGINT</span><span class="p">,</span> <span class="p">(</span><span class="n">__sighandler_t</span><span class="p">)</span><span class="n">SIG_IGN</span><span class="p">);</span>
    <span class="n">signal</span><span class="p">(</span><span class="n">SIGQUIT</span><span class="p">,</span> <span class="p">(</span><span class="n">__sighandler_t</span><span class="p">)</span><span class="n">SIG_IGN</span><span class="p">);</span>
    <span class="n">signal</span><span class="p">(</span><span class="n">SIGTERM</span><span class="p">,</span> <span class="p">(</span><span class="n">__sighandler_t</span><span class="p">)</span><span class="n">SIG_IGN</span><span class="p">);</span>
    <span class="cm">/* try to attach itself */</span>
    <span class="n">ptrace_output</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_ATTACH</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ptrace_output</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">puts</span><span class="p">(</span><span class="s">"OOPSIE WOOPSIE!! Uwu We made a mistaky wakey!!!!"</span><span class="p">);</span>
        <span class="n">kill</span><span class="p">(</span><span class="n">current_pid</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span>
    <span class="p">{</span>
        <span class="k">do</span>
        <span class="p">{</span>
            <span class="n">return_waitpid</span> <span class="o">=</span> <span class="n">waitpid</span><span class="p">(</span><span class="n">current_pid</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">wstatus</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">return_waitpid</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">return</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="n">local_2c</span> <span class="o">=</span> <span class="n">wstatus</span><span class="p">;</span>
            <span class="cm">/* WIFSTOPPED(wstatus) */</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">WIFSTOPPED</span><span class="p">(</span><span class="n">wstatus</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">local_28</span> <span class="o">=</span> <span class="n">wstatus</span><span class="p">;</span>
                <span class="cm">/* WEXITSTATUS(wstatus) */</span>
                <span class="n">stopsig</span> <span class="o">=</span> <span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">wstatus</span><span class="p">);</span>

                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'I'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'H'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'A'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'V'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'E'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'T'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'H'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'E'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'C'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'O'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">13</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'N'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">14</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'C'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">15</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'H'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">16</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">17</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'D'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">18</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'O'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">19</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'N'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">20</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\x05'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'T'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">22</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">23</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'I'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">24</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'N'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">25</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'T'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'E'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">27</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'R'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">28</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'R'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">29</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'U'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">30</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'P'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">31</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'T'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">32</span><span class="p">]</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">33</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'M'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">34</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'E'</span><span class="p">;</span>
                <span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">[</span><span class="mi">35</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>

                <span class="k">if</span> <span class="p">(</span><span class="n">stopsig</span> <span class="o">==</span> <span class="n">SIGSEGV</span><span class="p">)</span>
                <span class="p">{</span>
                    <span class="cm">/* catched SIGSEGV from second process
                       execution based on exception */</span>
                    <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_GETREGS</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                    <span class="n">return_inst_addr</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                    <span class="n">instruction</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mi">4</span><span class="p">),</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                    <span class="n">param1</span> <span class="o">=</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mi">8</span><span class="p">),</span>
                                                        <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                    <span class="n">param2</span> <span class="o">=</span> <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_PEEKDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mh">0xc</span><span class="p">),</span>
                                                <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                    <span class="k">do</span>
                    <span class="p">{</span>
                    <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">==</span> <span class="n">INS_XOR</span><span class="p">)</span>
                    <span class="p">{</span>
                        <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="p">(</span><span class="n">uint</span><span class="p">)</span><span class="n">param1</span> <span class="o">^</span> <span class="n">param2</span><span class="p">;</span>
                    <span class="p">}</span>
                    <span class="k">else</span>
                    <span class="p">{</span>
                        <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">&lt;</span> <span class="n">INS_XOR</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
                        <span class="p">{</span>
                            <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">==</span> <span class="n">INS_COMPARE_FLAG</span><span class="p">)</span>
                            <span class="p">{</span>
                                <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">param2</span><span class="p">;</span>
                                <span class="k">if</span> <span class="p">(</span><span class="n">param2</span> <span class="o">!=</span> <span class="mh">0xffffffff</span><span class="p">)</span>
                                <span class="p">{</span>
                                    <span class="n">read_data_from_memory</span><span class="p">(</span><span class="n">current_pid</span><span class="p">,</span> <span class="n">param1</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">flag</span><span class="p">,</span> <span class="mh">0x3e</span><span class="p">);</span>
                                    <span class="n">compare_with_no_flare</span> <span class="o">=</span> <span class="n">strncmp</span><span class="p">(</span><span class="n">flag</span> <span class="o">+</span> <span class="mh">0x30</span><span class="p">,</span> <span class="s">"@no-flare.com"</span><span class="p">,</span> <span class="mh">0xd</span><span class="p">);</span>
                                    <span class="k">if</span> <span class="p">(</span><span class="n">compare_with_no_flare</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
                                    <span class="p">{</span>
                                        <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
                                    <span class="p">}</span>
                                <span class="p">}</span>
                            <span class="p">}</span>
                            <span class="k">else</span>
                            <span class="p">{</span>
                                <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">==</span> <span class="n">INS_INCREMENT</span><span class="p">)</span>
                                <span class="p">{</span>
                                    <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">param1</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
                                <span class="p">}</span>
                                <span class="k">else</span>
                                <span class="p">{</span>
                                    <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">==</span> <span class="n">INS_DECRYPT_STRING_BYTE</span><span class="p">)</span>
                                    <span class="p">{</span>
                                        <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">param2</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">&amp;</span> <span class="mh">0xf</span> <span class="o">|</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">param1</span> <span class="o">+</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="mh">0x10</span><span class="p">;</span>
                                    <span class="p">}</span>
                                <span class="p">}</span>
                            <span class="p">}</span>
                        <span class="p">}</span>
                        <span class="k">else</span>
                        <span class="p">{</span>
                            <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">==</span> <span class="n">INS_ADD</span><span class="p">)</span>
                            <span class="p">{</span>
                                <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">param2</span> <span class="o">+</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">param1</span><span class="p">;</span>
                            <span class="p">}</span>
                            <span class="k">else</span>
                            <span class="p">{</span>
                                <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">==</span> <span class="n">INS_SET_TEA_KEY_SCHEDULE_CONSTANT</span><span class="p">)</span>
                                <span class="p">{</span>
                                    <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="o">-</span><span class="mh">0x61c88647</span><span class="p">;</span>
                                <span class="p">}</span>
                                <span class="k">else</span>
                                <span class="p">{</span>
                                    <span class="k">if</span> <span class="p">(</span><span class="n">instruction</span> <span class="o">==</span> <span class="n">INS_ROR</span><span class="p">)</span>
                                    <span class="p">{</span>
                                        <span class="n">regs</span><span class="p">.</span><span class="n">eax</span> <span class="o">=</span> <span class="n">ror</span><span class="p">((</span><span class="kt">long</span><span class="p">)</span><span class="n">param1</span><span class="p">,</span> <span class="n">param2</span><span class="p">);</span>
                                    <span class="p">}</span>
                                <span class="p">}</span>
                            <span class="p">}</span>
                        <span class="p">}</span>
                    <span class="p">}</span>
                    <span class="n">regs</span><span class="p">.</span><span class="n">eip</span> <span class="o">=</span> <span class="n">return_inst_addr</span><span class="p">;</span>
                    <span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">=</span> <span class="n">regs</span><span class="p">.</span><span class="n">esp</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span>
                    <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_SETREGS</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">regs</span><span class="p">);</span>
                    <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                <span class="p">}</span>
                <span class="k">else</span>
                <span class="p">{</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">stopsig</span> <span class="o">&lt;</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">SIGSEGV</span> <span class="o">+</span> <span class="mh">0x1</span><span class="p">))</span>
                    <span class="p">{</span>
                        <span class="k">if</span> <span class="p">(</span><span class="n">stopsig</span> <span class="o">==</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">SIGINT</span><span class="p">)</span>
                        <span class="p">{</span>
                            <span class="c1">// Interruption, fuck off</span>
                            <span class="n">puts</span><span class="p">(</span><span class="n">i_have_the_conch_dont_interrupt_me</span><span class="p">);</span>
                            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                        <span class="p">}</span>
                        <span class="k">else</span>
                        <span class="p">{</span>
                        <span class="nl">_continue_execution:</span>
                            <span class="cm">/* Continue with signal == 0 */</span>
                            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">);</span>
                        <span class="p">}</span>
                    <span class="p">}</span>
                    <span class="k">else</span>
                    <span class="p">{</span>
                        <span class="k">if</span> <span class="p">(</span><span class="n">stopsig</span> <span class="o">==</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">SIGALRM</span><span class="p">)</span>
                        <span class="p">{</span>
                            <span class="cm">/* Write one in kill_send */</span>
                            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_POKEDATA</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">kill_send</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x1</span><span class="p">);</span>
                            <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="n">stopsig</span><span class="p">);</span>
                            <span class="k">return</span><span class="p">;</span>
                        <span class="p">}</span>
                        <span class="k">if</span> <span class="p">(</span><span class="n">stopsig</span> <span class="o">!=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">SIGSTOP</span><span class="p">)</span>
                            <span class="k">goto</span> <span class="n">_continue_execution</span><span class="p">;</span>
                        <span class="n">call_real_ptrace</span><span class="p">(</span><span class="n">PTRACE_CONT</span><span class="p">,</span> <span class="n">current_pid</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x13</span><span class="p">);</span>
                    <span class="p">}</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span> <span class="k">while</span> <span class="p">((</span><span class="n">wstatus</span> <span class="o">&amp;</span> <span class="mh">0x7fU</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Reverse Engineering" /><category term="Linux" /><category term="ELF" /><category term="Linux" /><category term="Binary Analysis" /><category term="POSIX" /><summary type="html"><![CDATA[My personal notes about the Linux ptrace syscall]]></summary></entry><entry><title type="html">Madame De Maintenon’s Cryptographic Pursuit – Unmasking the Traitors</title><link href="https://fare9.github.io/reverse%20engineering/ctf/hexrays-challenge2/" rel="alternate" type="text/html" title="Madame De Maintenon’s Cryptographic Pursuit – Unmasking the Traitors" /><published>2023-11-24T00:00:00+00:00</published><updated>2023-11-24T17:40:00+00:00</updated><id>https://fare9.github.io/reverse%20engineering/ctf/hexrays-challenge2</id><content type="html" xml:base="https://fare9.github.io/reverse%20engineering/ctf/hexrays-challenge2/"><![CDATA[<figure>
<a href="/assets/images/hex-ray-challenge2/jiu-detective.jpg"><img src="/assets/images/hex-ray-challenge2/jiu-detective.jpg" /></a>
<figcaption>Detective Jiu has found a few clues, will be able to solve the riddle...?</figcaption>
</figure>

<p>Following my previous post on a Hex-Rays challenge (<a href="https://farena.in/symbolic%20execution/triton/hexrays-challenge-triton/">hexrays-challenge-triton</a>), my friend Robert Yates informed me about a new challenge from Hex-Rays, which was shared in this <a href="https://twitter.com/HexRaysSA/status/1724794320925098477">Tweet</a>. Intrigued, I decided to take on the challenge as a way to spend a boring weekend. In this write-up, I will illustrate how I successfully tackled the challenge step by step, utilizing various tools such as <a href="https://ghidra-sre.org/">Ghidra</a>, <a href="https://binary.ninja/">Binary Ninja</a>, <a href="https://github.com/hugsy/gef">GDB-Gef</a>, and a touch of <a href="https://triton-library.github.io/">Triton</a>.</p>

<h2 id="authors">Authors</h2>

<ul>
  <li>Eduardo Blázquez</li>
</ul>

<h2 id="the-challenge">The Challenge</h2>

<p>For this challenge, we are once again confronted with a 64-bit architecture ELF binary. It is dynamically linked and has a size of 31 kilobytes. To obtain this information, we can use the <code class="language-plaintext highlighter-rouge">file</code> command:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>file madame
<span class="go">madame: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ab32392967c6b82b041dc3389df9e226916506ed, for GNU/Linux 3.2.0, stripped
</span></code></pre></div></div>

<p>For this challenge, I began the analysis using the <em>Ghidra</em> disassembler. However, I also applied the same analysis using <em>Binary Ninja</em>, so most of the screenshots will be from the latter tool.</p>

<p>Let’s run the program to examine what we are dealing with. In case it prompts for input, you can simply enter anything as a basic test:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/1.png"><img src="/assets/images/hex-ray-challenge2/1.png" /></a>
<figcaption>Running the binary with an incorrect input.</figcaption>
</figure>

<p>From the previous image, it’s evident that the challenge sets the stage with some context and a brief narrative. Following the tradition of old video games, our task is to craft our own adventure and discover the right actions to navigate through the challenge and solve the riddle.</p>

<p>As a small spoiler, I’ll mention that four correct inputs are required to complete the challenge. Consequently, I’ll structure this post into sections, each dedicated to one of the inputs. But before delving into that, let’s commence the analysis of the challenge using Binary Ninja.</p>

<h3 id="analyzing-the-challenge-with-binary-ninja">Analyzing the Challenge with Binary Ninja</h3>

<p>This marks my inaugural experience with Binary Ninja, and I must say, it has proven to be remarkably user-friendly and intuitive. To initiate the analysis, one simply needs to launch the <code class="language-plaintext highlighter-rouge">binaryninja</code> executable, navigate to <code class="language-plaintext highlighter-rouge">File</code>, and select <code class="language-plaintext highlighter-rouge">Open</code>. Subsequently, we choose the <code class="language-plaintext highlighter-rouge">madame</code> binary for analysis. Binary Ninja adeptly identifies the <code class="language-plaintext highlighter-rouge">main</code> function, serving as our starting point for the analysis.</p>

<p>In my case, I’ve taken the liberty of renaming most variables and functions. Consequently, throughout this post, I’ll be referencing functions by their addresses, facilitating seamless navigation with any analysis tool. For this exploration in Binary Ninja, I’ll be utilizing the <code class="language-plaintext highlighter-rouge">High Level IL</code> representation.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/2.png"><img src="/assets/images/hex-ray-challenge2/2.png" /></a>
<figcaption>Main function from madame binary.</figcaption>
</figure>

<p>As mentioned earlier, the binary isn’t particularly large, and to successfully navigate the challenge, we must supply four inputs. In the preceding image, four calls to check functions are evident (located at addresses <code class="language-plaintext highlighter-rouge">0x004011e6</code>, <code class="language-plaintext highlighter-rouge">0x004011ed</code>, <code class="language-plaintext highlighter-rouge">0x004011f4</code>, and <code class="language-plaintext highlighter-rouge">0x004011fb</code>). The <code class="language-plaintext highlighter-rouge">main</code> function concludes with a jump to a final function at address <code class="language-plaintext highlighter-rouge">0x00401204</code>.</p>

<h4 id="first-steps-at-the-local-library">First steps at the local library</h4>

<p>The challenge begins with the following prompt: <em>You have heard that a rival historian recently discovered a copy of a chapter of the diary of Madame de Maintenon at the local library.</em> Our initial task unfolds at the local library, where we must discern the next course of action. By double-clicking on the first called function, we’ll delve into the analysis of the function located at address <code class="language-plaintext highlighter-rouge">0x00401894</code>.</p>

<h5 id="first-part-of-the-function">First part of the function</h5>

<p>Let’s examine the initial segment of the function. This function is obfuscated, and both in disassembly view and decompiler view, discerning its purpose proves challenging:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/3.png"><img src="/assets/images/hex-ray-challenge2/3.png" /></a>
<figcaption>First part of the function 0x00401894.</figcaption>
</figure>

<p>Following the analysis and utilizing GDB, it becomes apparent that the value to be stored in the variable <code class="language-plaintext highlighter-rouge">rdx_2</code> is derived from the length of a buffer read with a call at address <code class="language-plaintext highlighter-rouge">0x004018fc</code>. Towards the end of the code, there’s a check to ascertain whether this length is less than 18 or equal to 18.</p>

<p>This code ultimately verifies that the length is neither less than 18 nor equal to 18, indicating that we are in search of a string longer than 18 characters.</p>

<h5 id="small-stop-at-read-function">Small stop at <code class="language-plaintext highlighter-rouge">read</code> function</h5>

<p>Now, let’s take a preliminary look at the <code class="language-plaintext highlighter-rouge">read</code> function located at address <code class="language-plaintext highlighter-rouge">0x00402370</code>. While we won’t delve into the details at this point, our focus is to gain an initial understanding of what transpires with the <code class="language-plaintext highlighter-rouge">buffer</code> supplied as a parameter.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/4.png"><img src="/assets/images/hex-ray-challenge2/4.png" /></a>
<figcaption>Read function at address 0x00402370.</figcaption>
</figure>

<p>The function starts with two checks that internally involve <code class="language-plaintext highlighter-rouge">__builtin_memcpy</code>. These two <code class="language-plaintext highlighter-rouge">memcpy</code> instances have been generated by Binary Ninja after recognizing the following pattern as a <code class="language-plaintext highlighter-rouge">memcpy</code>:</p>

<pre><code class="language-assembly">00402382  488d35174b0000     lea     rsi, [rel second_public_key]  {"678dcc64ccf7c29ffe64838a80196bd9…"}
00402389  488d3d10540000     lea     rdi, [rel first_public_key]  {"8e449627141446d50a3bfab5d9fc0d58…"}
00402390  b940000000         mov     ecx, 0x40
00402395  f348a5             rep movsq qword [rdi], [rsi]  {0x0}
</code></pre>

<p>However, we will skip over that portion of the code and direct our attention to the subsequent loop. This loop is designed to read a maximum of 200 bytes into the input-provided buffer. It restricts acceptance to characters whose representation is lower than <code class="language-plaintext highlighter-rouge">0x7e</code>, essentially allowing only printable characters.</p>

<p>In essence, we have a secure reading function for a buffer supplied as a parameter to the function.</p>

<h5 id="second-part-of-the-function">Second part of the function</h5>

<p>Now, let’s proceed with the initial check function. The first segment of the function involved an obfuscated <code class="language-plaintext highlighter-rouge">strlen</code>. The subsequent image illustrates the second part:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/5.png"><img src="/assets/images/hex-ray-challenge2/5.png" /></a>
<figcaption>Second part of the function 0x00401894.</figcaption>
</figure>

<p>It’s noteworthy that initially, the variable <code class="language-plaintext highlighter-rouge">rsi_1</code> points to the string <em>“Head to the library”</em>, while the variable <code class="language-plaintext highlighter-rouge">rdi_1</code> points to the buffer. Subsequently, a while loop systematically compares them character by character using the following lines:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>equal_18 = temp2_1 == temp3_1
</code></pre></div></div>

<p>The loop terminates when the variable <code class="language-plaintext highlighter-rouge">equal_18</code> becomes equal to <code class="language-plaintext highlighter-rouge">0</code>, indicating that the characters being compared are different. This function sets the variable <code class="language-plaintext highlighter-rouge">i.b</code> and checks if the value is equal to zero. This behavior aligns with that of <code class="language-plaintext highlighter-rouge">strcmp</code>, a function that compares two strings and returns <code class="language-plaintext highlighter-rouge">0</code> when the strings are identical.</p>

<p>In essence, we have two functions in an obfuscated representation: <code class="language-plaintext highlighter-rouge">strlen</code> and <code class="language-plaintext highlighter-rouge">strcmp</code>. The comparison is performed against the string <em>“Head to the library”</em>.</p>

<h5 id="third-part-of-the-function">Third part of the function</h5>

<p>As we conclude this function, we begin encountering calls to <code class="language-plaintext highlighter-rouge">AES</code> functions. <code class="language-plaintext highlighter-rouge">AES</code> is a symmetric block cipher that employs the same key for both encryption and decryption.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/6.png"><img src="/assets/images/hex-ray-challenge2/6.png" /></a>
<figcaption>Third part of the function 0x00401894.</figcaption>
</figure>

<p>In this segment of the function, the 19 bytes from the input (the length from the previous string) serve as the key. This key is then used to decrypt a buffer of 0x600 bytes.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/7.png"><img src="/assets/images/hex-ray-challenge2/7.png" /></a>
<figcaption>First decrypted buffer.</figcaption>
</figure>

<p>It appears that the correct flag is utilized to decrypt another string, likely the next part of the riddle!</p>

<h4 id="finishing-the-first-check">Finishing the First Check</h4>

<p>We will attempt to provide the string <em>“Head to the library”</em> as input and see if we can glean more information from the challenge.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/8.png"><img src="/assets/images/hex-ray-challenge2/8.png" /></a>
<figcaption>Using the first flag.</figcaption>
</figure>

<p>As observed, providing the string yields the next part of the story and reveals the string <em>01000010</em> as the first clue for the riddle. Let’s retain this data as it may prove useful for the rest of the challenge.</p>

<ul>
  <li><strong>First Flag:</strong> <em>“Head to the library”</em></li>
  <li><strong>First Clue:</strong> 01000010</li>
</ul>

<h4 id="the-book-that-fell-from-the-shelf">The Book that Fell from the Shelf</h4>

<p>We concluded the previous section with the text: <em>“The page was lying on the shelf in the open, maybe it fell from somewhere. You see a few more loose pages sticking out of some other books around you. What happened here?”</em></p>

<p>As the story progresses, so shall we. Let’s directly transition to the second check function, located at address <code class="language-plaintext highlighter-rouge">0x00401a50</code>. Once again, we will break down the analysis step by step.</p>

<h5 id="first-part-of-the-function-1">First Part of the Function</h5>

<p>The pivotal segment of this function is its initial part, where we once again encounter the reading of a buffer and a subsequent call to a comparison function.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/9.png"><img src="/assets/images/hex-ray-challenge2/9.png" /></a>
<figcaption>First part of the function 0x00401a50.</figcaption>
</figure>

<p>Here, the program prompts us with <em>“What do you do?”</em>, and immediately after the <code class="language-plaintext highlighter-rouge">read</code>, there is a call to a function I’ve named <code class="language-plaintext highlighter-rouge">cmpSecondFlag</code>, found at the address <code class="language-plaintext highlighter-rouge">0x00402560</code>. Let’s proceed to analyze that function.</p>

<h5 id="analysis-of-comparison-function">Analysis of Comparison Function</h5>

<p>Let’s delve into the function and understand how the second flag is examined.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/10.png"><img src="/assets/images/hex-ray-challenge2/10.png" /></a>
<figcaption>Comparison function at address 0x00402560.</figcaption>
</figure>

<p>To begin, the function copies two byte arrays into local buffers, one labeled <code class="language-plaintext highlighter-rouge">xor_buffer</code> and the other <code class="language-plaintext highlighter-rouge">cmp_buffer</code>. The representation of <code class="language-plaintext highlighter-rouge">cmp_buffer</code> in this display is not complete, as the disassembler reveals an instruction that copies a final byte:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>004025b6  c644241c9f         mov     byte [rsp+0x1c {var_12c}], 0x9f
</code></pre></div></div>

<p>Applying a final fix, here are the buffers:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>xor_buffer = "\x44\x36\x63\xc8\x1c\x28\x84\xa0\x8d\x3a\x2f\x39\xf7\xee\x92\x4f\xa7\xd5\xd3\x6c\x81\x8c\x4f\xcd\x37\x17\x89\xfc\xf9\x1c\xc2\x1b"
cmp_buffer = "\x07\x5e\x06\xab\x77\x08\xe6\xcf\xe2\x51\x5c\x19\x98\x80\xb2\x3b\xcf\xb0\xf3\x02\xe4\xf4\x3b\xed\x44\x7f\xec\x90\x9f"
</code></pre></div></div>

<p>Then, using <code class="language-plaintext highlighter-rouge">strncpy</code>, the buffer given as a parameter is copied into a local buffer. Subsequently, we encounter two loops: the first of them performs an XOR operation on the provided buffer with the first buffer (<code class="language-plaintext highlighter-rouge">xor_buffer</code>), and the second loop is employed to compare the resulting buffer with the second copied buffer (<code class="language-plaintext highlighter-rouge">cmp_buffer</code>). This reveals a straightforward encryption mechanism based on XOR operations with a hardcoded buffer.</p>

<p>To retrieve the final flag, we can utilize the following Python script:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x44\x36\x63\xc8\x1c\x28\x84\xa0\x8d\x3a\x2f\x39\xf7\xee\x92\x4f\xa7\xd5\xd3\x6c\x81\x8c\x4f\xcd\x37\x17\x89\xfc\xf9\x1c\xc2\x1b</span><span class="s">"</span>
<span class="n">b</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x07\x5e\x06\xab\x77\x08\xe6\xcf\xe2\x51\x5c\x19\x98\x80\xb2\x3b\xcf\xb0\xf3\x02\xe4\xf4\x3b\xed\x44\x7f\xec\x90\x9f</span><span class="s">"</span>

<span class="n">flag</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">b</span><span class="p">)):</span>
    <span class="n">c</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="n">b</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
    <span class="n">flag</span> <span class="o">+=</span> <span class="n">c</span>

<span class="k">print</span><span class="p">(</span><span class="s">"The final flag is: %s"</span> <span class="o">%</span> <span class="p">(</span><span class="n">flag</span><span class="p">))</span>
</code></pre></div></div>

<p>Running the script gives us the next output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The final flag is: Check books on the next shelf
</code></pre></div></div>

<p>So we obtained the second flag!</p>

<h4 id="second-part-of-the-function-1">Second Part of the Function</h4>

<p>Before delving into the second flag, let’s conclude the analysis of the second comparison function.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/11.png"><img src="/assets/images/hex-ray-challenge2/11.png" /></a>
<figcaption>Second part of the function 0x00401a50.</figcaption>
</figure>

<p>For now, we’ll skip over the copy from <code class="language-plaintext highlighter-rouge">second_buffer</code> to <code class="language-plaintext highlighter-rouge">encrypted_buffer</code> and the calls to <code class="language-plaintext highlighter-rouge">keyMethod</code> since we’ll explore them at the end of this post. Once again, we observe that the user’s buffer is employed as an AES key to decrypt another buffer, likely the subsequent buffer to be presented to the user.</p>

<h4 id="finishing-the-second-check">Finishing the Second Check</h4>

<p>We will utilize the message as a flag for the second part of the challenge and observe the outcome.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/12.png"><img src="/assets/images/hex-ray-challenge2/12.png" /></a>
<figcaption>Entering the second flag and obtaining the third message.</figcaption>
</figure>

<p>It appears that the sentence <em>“Check books on the next shelf”</em> serves as the correct flag, leading us to acquire a third message. Once again, let’s retain the flag and the new clue:</p>

<ul>
  <li><strong>Second Flag:</strong> <em>“Check books on the next shelf”</em></li>
  <li><strong>Second Clue:</strong> 00110111</li>
</ul>

<h4 id="where-are-the-rest-of-the-clues">Where are the rest of the clues?</h4>

<figure>
<a href="/assets/images/hex-ray-challenge2/jiu-detective2.png"><img src="/assets/images/hex-ray-challenge2/jiu-detective2.png" /></a>
<figcaption>Detective Jiu has found already two clues, will be able to find the rest?</figcaption>
</figure>

<p>We have reached the halfway point of this trip, and we will continue with the third check. Let’s dive straight into the function and discover what kind of check we have to solve this time.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/13.png"><img src="/assets/images/hex-ray-challenge2/13.png" /></a>
<figcaption>Beginning of the third comparison function at the address 0x00401cd0.</figcaption>
</figure>

<p>This function is nearly identical to the second comparison. It begins by reading a buffer of 200 characters and then immediately jumps to the comparison function. If the comparison returns 0, the control flow will redirect to a <code class="language-plaintext highlighter-rouge">puts</code> function followed by an <code class="language-plaintext highlighter-rouge">exit</code>, resulting in the printing of the following text: <em>“Where could the third page possibly be? How could your fellow historian have been so careless with such a priceless artifact?”</em> Therefore, we should make every effort to prevent the comparison from returning 0.</p>

<h5 id="analysis-of-the-comparison-function">Analysis of the comparison function</h5>

<p>The third check is located at the address <em>0x00401300</em>. In this function, a character-by-character comparison takes place, accompanied by a straightforward mathematical operation for each character. The complete function is illustrated in the following images:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/14.png"><img src="/assets/images/hex-ray-challenge2/14.png" /></a>
<a href="/assets/images/hex-ray-challenge2/15.png"><img src="/assets/images/hex-ray-challenge2/15.png" /></a>
<a href="/assets/images/hex-ray-challenge2/16.png"><img src="/assets/images/hex-ray-challenge2/16.png" /></a>
<figcaption>Third comparison function from the challenge.</figcaption>
</figure>

<p>To solve this, all we need to do is apply the inverse operation for each line. You can use the following Python script to simplify the process:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">flag</span> <span class="o">=</span> <span class="s">""</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x62</span> <span class="o">-</span> <span class="mh">0xf</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x5e</span> <span class="o">^</span> <span class="mh">0x3b</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x9a</span> <span class="o">-</span> <span class="mh">0x39</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x4a</span> <span class="o">^</span> <span class="mh">0x38</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x17</span> <span class="o">^</span> <span class="mh">0x74</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x53</span> <span class="o">^</span> <span class="mh">0x3b</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x23</span> <span class="o">-</span> <span class="mi">3</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x31</span> <span class="o">+</span> <span class="mh">0x43</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x71</span> <span class="o">-</span> <span class="mi">9</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x71</span> <span class="o">-</span> <span class="mh">0xc</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x7a</span> <span class="o">-</span> <span class="mh">0x5a</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x52</span> <span class="o">+</span> <span class="mh">0x10</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xea</span> <span class="o">-</span> <span class="mh">0x7b</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x46</span> <span class="o">^</span> <span class="mh">0x29</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xec</span> <span class="o">+</span> <span class="mh">0x7f</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x22</span> <span class="o">^</span> <span class="mi">2</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xba</span> <span class="o">-</span> <span class="mh">0x54</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xdf</span> <span class="o">^</span> <span class="mh">0xb0</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xd8</span> <span class="o">-</span> <span class="mh">0x66</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xb3</span> <span class="o">+</span> <span class="mh">0x6d</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x43</span> <span class="o">^</span> <span class="mh">0x20</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xdb</span> <span class="o">+</span> <span class="mh">0x91</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x8d</span> <span class="o">+</span> <span class="mh">0xe8</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x6e</span> <span class="o">+</span> <span class="mh">0xf7</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xa3</span> <span class="o">-</span> <span class="mh">0x30</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xed</span> <span class="o">+</span> <span class="mh">0x13</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0xc3</span> <span class="o">+</span> <span class="mh">0x3d</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x93</span> <span class="o">+</span> <span class="mh">0x6d</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x8a</span> <span class="o">+</span> <span class="mh">0x76</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x7e</span> <span class="o">+</span> <span class="mh">0x82</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x2a</span> <span class="o">-</span> <span class="mh">0x2a</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x5c</span> <span class="o">^</span> <span class="mh">0x5c</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span> 
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</code></pre></div></div>

<p>But if we are using Ghidra, we will be able to see the solution directly in the decompiler:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/17.png"><img src="/assets/images/hex-ray-challenge2/17.png" /></a>
<figcaption>Decompiler from Ghidra showing the solution byte by byte.</figcaption>
</figure>

<p>Running the python script:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>python third_flag.py
<span class="go">Search the book for clues
</span></code></pre></div></div>

<p>So, it looks like we have to continue looking for clues in the book, and probably our third flag will be <em>Search the book for clues</em>.</p>

<h5 id="end-of-third-check-function">End of third check function</h5>

<p>This function ends in the same way than the second, it uses the flag for decrypting a big buffer:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/18.png"><img src="/assets/images/hex-ray-challenge2/18.png" /></a>
<figcaption>Final part of function at the address 0x00401cd0.</figcaption>
</figure>

<h5 id="finishing-the-third-check-function">Finishing the third check function</h5>

<p>Now, let’s attempt to solve the third check function using the flag we obtained earlier, <em>Search the book for clues</em>, and observe the results:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/19.png"><img src="/assets/images/hex-ray-challenge2/19.png" /></a>
<figcaption>Entering the third flag, and obtaining the fourth message.</figcaption>
</figure>

<p>It looks like we obtained a correct flag, and with that the fourth message and the third clue.</p>

<p>Third flag: <em>“Search the book for clues”</em></p>

<p>Third clue: 10110010.</p>

<h4 id="end-of-the-world-as-we-know-it">End of the world! (as we know it)</h4>

<p>We are nearing the end of this journey, with just one more flag to obtain. The function at address 0x00401f50 resembles the previous ones – it prompts us for our flag and stores it in a buffer with a size of 200 characters. Once again, we encounter a <code class="language-plaintext highlighter-rouge">puts</code> message asking, <em>“What do you do?”</em>, followed by a call to the <code class="language-plaintext highlighter-rouge">read</code> function from the binary. After this, the final check function at address 0x004016f0 is invoked. This sequence is illustrated in the following image:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/20.png"><img src="/assets/images/hex-ray-challenge2/20.png" /></a>
<figcaption>Beginning of the function 0x00401f50, last check.</figcaption>
</figure>

<p>Now we will jump to the comparison function, in order to retrieve the last flag!</p>

<h5 id="retrieving-the-last-flag">Retrieving the last flag</h5>

<p>The last function at the address 0x004016f0 will make a very simple comparison using <code class="language-plaintext highlighter-rouge">strncmp</code> from our buffer, and another buffer decrypted using <code class="language-plaintext highlighter-rouge">AES</code>, we can see it in the next picture:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/21.png"><img src="/assets/images/hex-ray-challenge2/21.png" /></a>
<figcaption>Function 0x004016f0, last comparison from the program.</figcaption>
</figure>

<p>While we can retrieve the AES key, and write a program to decrypt the last flag, we will go with the easy way, and we will use <code class="language-plaintext highlighter-rouge">gdb</code> debugger in order to retrieve the parameters from the <code class="language-plaintext highlighter-rouge">strncmp</code> function. We can set a breakpoint in the address 0x0040179e, and enter the previous flags to reach to the last one.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/22.png"><img src="/assets/images/hex-ray-challenge2/22.png" /></a>
<figcaption>Running gdb-gef for obtaining the last flag.</figcaption>
</figure>

<p>If we introduce the correct flags, and we reach the breakpoint, we will see one of the parameters with the correct flag. Since I do not have the fourth flag I will just enter the next string <em>“This is a test!”</em>, and as we can see in the next image, we obtain the final flag!</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/23.png"><img src="/assets/images/hex-ray-challenge2/23.png" /></a>
<figcaption>Obtaining the last flag!</figcaption>
</figure>

<p>And we obtain the last flag which is the string <em>“Turn over the page”</em>, and with this we will have the four flags, and the challenge is over, we can finally <em>Praise the Sun</em>.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/praise_the_sun.jpg"><img src="/assets/images/hex-ray-challenge2/praise_the_sun.jpg" /></a>
</figure>

<p>Now we will enter the last flag into our program, and then retrieve the solution as expected in all this kind of challenges. So let’s go with it!</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/24.png"><img src="/assets/images/hex-ray-challenge2/24.png" /></a>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge2/wtf.jpeg"><img src="/assets/images/hex-ray-challenge2/wtf.jpeg" /></a>
</figure>

<p>WTF happened? We obtained the four flags, but it’s telling us the next:</p>

<p><em>What does this mean? You’ve worked so hard but yet still don’t have the information you seek? What now?</em>
<em>You have all four pages your rival claimed to have found, and yet are no closer to the truth.</em>
<em>After several hours of fruitlessly searching for meaning in the messages, you give up and turn to leave in defeat.</em></p>

<p>So it looks like we were not right, or at least completely right with the flags. In any case, let’s keep this fourth flag and the last clue.</p>

<p>Fourth flag: <em>“Turn over the page”</em></p>

<p>Fourth clue: 00000101.</p>

<h4 id="the-real-end">The Real End</h4>

<p>In this point is where we realize that we didn’t finish the challenge, and it was too easy for being a reverse engineering challenge. We will now start our analysis with the last function, and from this last function we will dig into other functions that will provide us with the final answer. The analysis now will start with the function at the address 0x00402640.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/25.png"><img src="/assets/images/hex-ray-challenge2/25.png" /></a>
</figure>

<p>We have here three variables that are checked to be different to 0, <code class="language-plaintext highlighter-rouge">CHECK1</code>, <code class="language-plaintext highlighter-rouge">CHECK2</code> and <code class="language-plaintext highlighter-rouge">CHECK3</code>. We will have to look where these variables are set to a value different to 0. We find the write cross-reference in the function at the address 0x004021e0.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/26.png"><img src="/assets/images/hex-ray-challenge2/26.png" /></a>
</figure>

<p>In the previous image we have the function that will modify those global variables, but how these global variables are set to 1?. First of all a <code class="language-plaintext highlighter-rouge">memcmp</code> must return the value 0 (two buffers are the same). Let’s analyze a little bit more. The function starts retrieving two big numbers, one is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>8e449627141446d50a3bfab5d9fc0d58c6b9f64630d011cb5c831c5989402de1f553ae70c9f8ddefb42f001e553fe7d852bb08cec6efebe490eb40c91955b020159c66836a5d7d5364da7cab32deff4ea6ec1e41bdda7b7c298da68d4be77e4750bf86d5d24ed67511bb37a105bc4da0e3ec0cd4960a1ae2986fd402101061d290f292030bcf21a38d77dbde760d01a3faaa210e34a4e471fa0eac5518d2f01faa70659f582a9e211ff6b438b0bb1abb49f4bb458acefd7bbcc8f68ed7cd121bf16ad1d5e0cd5384b4e3441de7d5ec3c10c52ed9263ffe3c6af5ba508f0b774e932dece2f84c053f972ca31a68c1cd13668db6adb3e2320c93a0b06ae1737ad9
</code></pre></div></div>

<p>And the other is the value <code class="language-plaintext highlighter-rouge">3</code>. These are used as the <em>module</em> and the <em>exponent</em> for generating a RSA public key. Then a variable called <em>global_user_buffer</em> is encrypted with that RSA public key, and compared with a buffer, the beginning of the buffer is presented in the next picture:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/27.png"><img src="/assets/images/hex-ray-challenge2/27.png" /></a>
</figure>

<p>For those who do not understand why it is almost impossible to decrypt the buffer, in the next link you can find the theory of <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">public key cryptography</a>.</p>

<p>But two questions, where does the buffer <em>global_user_buffer</em> comes, and where this <em>keyMethod</em> is called from?</p>

<p>If we follow the cross references from <em>global_user_buffer</em>, we can see that this value is written in the first function for the flag check (we called it <em>firstFlagCheck</em> at the address 0x00401870). This value is exactly the first buffer the user introduced, we can see it in the next image:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/28.png"><img src="/assets/images/hex-ray-challenge2/28.png" /></a>
</figure>

<p>Also, we can see from the previous image that the <em>global_user_buffer</em> is written once the check from the first flag is correct, so the flag <em>Head to the library</em> is correct, but it looks like the comparison after the RSA encryption is not working.</p>

<p>And now where is called this <code class="language-plaintext highlighter-rouge">keyMethod</code> function? We check the references with Binary Ninja, and we can see that this function is called always at the end of each function used to check each flag:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/29.png"><img src="/assets/images/hex-ray-challenge2/29.png" /></a>
</figure>

<h5 id="understanding-the-comparisons-flow">Understanding the comparisons flow</h5>

<p>So we have a comparison that works more or less like the next pseudo-code:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>module = 0x8e449627141446d50a3bfab5d9fc0d58c6b9f64630d011cb...
exponent = 3
public_key = RSA_PUBLIC_KEY(module, exponent, 0)

final_buffer = 0x7d9e6b093218080a5a34349c0db3c3c986b102d9...
encrypted_buffer = RSA_ENCRYPT(user_buffer, public_key)

is_buffer_correct = final_buffer == encrypted_buffer
</code></pre></div></div>

<p>If we analyze the program, we can go to three different points. The first one is the <code class="language-plaintext highlighter-rouge">read</code> function, where we were able to see the next code:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/30.png"><img src="/assets/images/hex-ray-challenge2/30.png" /></a>
</figure>

<p>We had two comparisons and two conditional codes, that in case the global variables <code class="language-plaintext highlighter-rouge">CHECK2</code> and <code class="language-plaintext highlighter-rouge">CHECK3</code> are different to 0, they would replace the <code class="language-plaintext highlighter-rouge">module</code> from the previous pseudo-code, with two other different values (two different modules), next we have those two different numbers:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>678dcc64ccf7c29ffe64838a80196bd90b2d6247e4d712cb60c6a4a3a09ac088b9d1b19518451ce1a295ca6134a65cb5176083849e11cea23cf5d6c303ee95d02f1af26f741131d03c4e86866e26b09069c0be5c718298ed1cfc01493d78520957e25c2d921f6b6518ef5ef608e209d4d9ad613fdb6a2eb4156c906c89583949ca076312c6a258f14794ee852a61f27fe2a6b17b1ea85de3e40a2636fc4430e920ed8dc688aebdb6f5e63140f7844f3597c82704545c308a36e20eb94e00b35eaee860835c2f213956bfb79bb17d9b914524a5b133be5af4667ca0710420ca6bd90c28761ba1d52ed7d83d927245f53d45b35f2f1729ff602271abb0ebf7ce5b
</code></pre></div></div>

<p>And the next one:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b1b751bdef5727862c0f6bddcaa9802722b2499c760e02d7bb4c38629339194431dbeb41a6222e01dca0fa8e792562ccc9bcf9c57549037a44eb4945daf4440ac4f4aab3bdf1566a3961c88e8cdb925870e68e9064354568335eefc62344fdac06593bdd8c4dc63c0af932f5dab986919f4acb4b602896ba1896c3d0bc00a9bd6408a85e3e8766bfd44af0ab151d3537c2b2955eebe9cbcd6871146524253e14e374cdda166e8b298932695c774ab8f8ac332a92fa49c91f65ce1a01b12e3d056990c954a3c6fa9346a67819bbc76d9cfbebff9810841810ccfdd3a3773cc24ead32665b8e667b1b0b817f0bb3d8d7ca17342e6b2d024762e2ecbf897af9cb15
</code></pre></div></div>

<p>So it looks like in total, the program contains 3 modules that can be used to generate 3 RSA public keys.</p>

<p>Now we can move to the functions at the addresses 0x00401a50 (<code class="language-plaintext highlighter-rouge">secondFlagCheck</code>) and to the function at the address 0x00401cd0 (<code class="language-plaintext highlighter-rouge">thirdFlagCheck</code>). In <code class="language-plaintext highlighter-rouge">secondFlagCheck</code> we had the next code:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/31.png"><img src="/assets/images/hex-ray-challenge2/31.png" /></a>
</figure>

<p>The encrypted buffer that was used for the comparison is replaced by another buffer. And if we move to the <code class="language-plaintext highlighter-rouge">thirdFlagCheck</code>, we can see the next:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/32.png"><img src="/assets/images/hex-ray-challenge2/32.png" /></a>
</figure>

<p>We have the same code as before, the encrypted buffer is replaced by a third buffer. We have the next:</p>

<ul>
  <li>Three modules for RSA keys.</li>
  <li>Three encrypted buffers used for comparison</li>
  <li>An exponent with value 3</li>
</ul>

<p>We can see the flow of these checks in the next scheme:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/flow.png"><img src="/assets/images/hex-ray-challenge2/flow.png" /></a>
</figure>

<p>So although we only have one function for checking, we use different modules each time, and the user buffer is compared against three different encrypted buffers.</p>

<h5 id="chinese-remainder-theorem">Chinese Remainder Theorem</h5>

<p>We now have to solve a big problem which is finding what is the correct input we need for the first flag, having different RSA modules for public keys, and three different encrypted messages.</p>

<p>Here we will use an attack for RSA known as <strong>Low Exponent Attack</strong>. While I am not a crypto expert, we will see in what this attack is based. So if we have three encrypted messages with the next shape:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>c1 = c (mod p1)
c2 = c (mod p2)
c3 = c (mod p3)
</code></pre></div></div>

<p>We can recover this <code class="language-plaintext highlighter-rouge">c</code> value, using the Chinese Remainder Theorem. Given the fact that both encrypted messages (<code class="language-plaintext highlighter-rouge">cX</code>) and the modulus from the equations (<code class="language-plaintext highlighter-rouge">pX</code>) are coprimes to each other.</p>

<p>In our case <code class="language-plaintext highlighter-rouge">c</code> is the value m^3, where <code class="language-plaintext highlighter-rouge">m</code> is our message we want to recover, and recover <code class="language-plaintext highlighter-rouge">m</code> will be easy since it will be finding the cube root from <code class="language-plaintext highlighter-rouge">c</code>.</p>

<p>You can find more information about this attack in the next <a href="https://yurichev.org/RSA_low/">post</a> by Dennis Yurichev, highly recommended.</p>

<p>So we will have to solve the equations system to retrieve m^3, and then apply the cube root in order to retrieve the message decrypted, for the solution I have adapted the code from the next <a href="https://asecuritysite.com/ctf/rsa_ctf02">post</a>. I just added the modules from our binary, and the encrypted buffers. You can find next the python code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span><span class="p">,</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">Crypto</span> <span class="kn">import</span> <span class="n">Random</span>
<span class="kn">import</span> <span class="nn">Crypto</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">libnum</span>

<span class="n">e</span><span class="o">=</span><span class="mi">3</span>
<span class="n">n1</span><span class="o">=</span><span class="mh">0x8e449627141446d50a3bfab5d9fc0d58c6b9f64630d011cb5c831c5989402de1f553ae70c9f8ddefb42f001e553fe7d852bb08cec6efebe490eb40c91955b020159c66836a5d7d5364da7cab32deff4ea6ec1e41bdda7b7c298da68d4be77e4750bf86d5d24ed67511bb37a105bc4da0e3ec0cd4960a1ae2986fd402101061d290f292030bcf21a38d77dbde760d01a3faaa210e34a4e471fa0eac5518d2f01faa70659f582a9e211ff6b438b0bb1abb49f4bb458acefd7bbcc8f68ed7cd121bf16ad1d5e0cd5384b4e3441de7d5ec3c10c52ed9263ffe3c6af5ba508f0b774e932dece2f84c053f972ca31a68c1cd13668db6adb3e2320c93a0b06ae1737ad9</span>
<span class="n">c1</span><span class="o">=</span><span class="mh">0x7d9e6b093218080a5a34349c0db3c3c986b102d98c14cda70bb241b5a838394cabb132d9789deade34ca28a3967b77e1da56c428f40c7d601be4ae2cb98fee1b8c8dcb22eeedfc4bb6462a9c24d4fd45854d5dc04f58e5bc701b6cac9ed6d02ba05b8935c7fe26f84086cd49d0d66bcb6575aaa791f81be84768b5961f3ff105ee5ec56fcdaf46a1c7369dd4d58ecd2ce28c7abb0f35e0dc0752a11b8916969af491f6baafbffe0877fae05ba18d6daf385bccd88951d72e6b8a4ccca00fa3bf451f512eaebf8a20baad68e04caae68b8fa1dbcbd1ae377b5cf26a7c90b6348569036d76d838b5bcd0e6c423581265edccf32279a0b629fab0fcd485a38b4205</span>
<span class="n">n2</span><span class="o">=</span><span class="mh">0x678dcc64ccf7c29ffe64838a80196bd90b2d6247e4d712cb60c6a4a3a09ac088b9d1b19518451ce1a295ca6134a65cb5176083849e11cea23cf5d6c303ee95d02f1af26f741131d03c4e86866e26b09069c0be5c718298ed1cfc01493d78520957e25c2d921f6b6518ef5ef608e209d4d9ad613fdb6a2eb4156c906c89583949ca076312c6a258f14794ee852a61f27fe2a6b17b1ea85de3e40a2636fc4430e920ed8dc688aebdb6f5e63140f7844f3597c82704545c308a36e20eb94e00b35eaee860835c2f213956bfb79bb17d9b914524a5b133be5af4667ca0710420ca6bd90c28761ba1d52ed7d83d927245f53d45b35f2f1729ff602271abb0ebf7ce5b</span>
<span class="n">c2</span><span class="o">=</span><span class="mh">0x67512e54ff9cd853ab645a69ec8f64009fad60eee84ce5d9a5db8754813d5f9c9c038da9476caf9f1b543a289613d02a4addc2948b94a965b2dce0cb93b771236a7f1cf879c86c4f9c07f26bbbd773a7d9edf6b3981e4f96f355ecdd7407506672e5025ec2c915ca1d5f35d1ccc35679aff91b833a07fc6bfad06c9acf053870e5f52d3dc8f1757355ea4c8da81d88c37d4b68ebe50274566cb683c19cf5fa6d8851f92d9f9abd5fd0cbb67551c3fa2018555b9a2995da96443d9746399fbb86aca121fe4ebe97d8468db22a0bd087a1e3fc289c5633157bdc0bcd677faa26b1fa4be84285a408edd28e48ab47535465dce281111b0b70855cae188aa6fdaa85</span>
<span class="n">n3</span><span class="o">=</span><span class="mh">0xb1b751bdef5727862c0f6bddcaa9802722b2499c760e02d7bb4c38629339194431dbeb41a6222e01dca0fa8e792562ccc9bcf9c57549037a44eb4945daf4440ac4f4aab3bdf1566a3961c88e8cdb925870e68e9064354568335eefc62344fdac06593bdd8c4dc63c0af932f5dab986919f4acb4b602896ba1896c3d0bc00a9bd6408a85e3e8766bfd44af0ab151d3537c2b2955eebe9cbcd6871146524253e14e374cdda166e8b298932695c774ab8f8ac332a92fa49c91f65ce1a01b12e3d056990c954a3c6fa9346a67819bbc76d9cfbebff9810841810ccfdd3a3773cc24ead32665b8e667b1b0b817f0bb3d8d7ca17342e6b2d024762e2ecbf897af9cb15</span>
<span class="n">c3</span><span class="o">=</span><span class="mh">0x1b48f3de27db0a80ffa291b161ffe9ca6cee79db559c8047579920cb23c130311a366f8561ee5966ee0a72293671c3587074011759de78b837b676303c0179db6cfc6e5d883835738249bc61f8ebc6a6cade877eee27f2f74c510f9ac6c723e53f76a8d45db5d6918cee530db1a2102781a481cd0930875b5f40c61a35e685364c5ec883bf5899238eddc22ba12cb58fcee49e943c58b13f5cd893ff4c02cdb583ea3359cd26b8360a1873498b4d650c580e5f2ea31f2472a7f8d9a5ee30237c4addc4876961ab80f2923e807dbc319d7e4aaec4c63e1402f68d9d11ff0365a70328e62aa5da8f1d1b62035381b1a05744e78ab06d1d69bfd45eb41e4e902338</span>

<span class="n">mod</span><span class="o">=</span><span class="p">[</span><span class="n">n1</span><span class="p">,</span><span class="n">n2</span><span class="p">,</span><span class="n">n3</span><span class="p">]</span>
<span class="n">rem</span><span class="o">=</span><span class="p">[</span><span class="n">c1</span><span class="p">,</span><span class="n">c2</span><span class="p">,</span><span class="n">c3</span><span class="p">]</span>

<span class="n">res</span><span class="o">=</span><span class="n">libnum</span><span class="p">.</span><span class="n">solve_crt</span><span class="p">(</span><span class="n">rem</span><span class="p">,</span> <span class="n">mod</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n\n</span><span class="s">Answer:"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="se">\n</span><span class="s">Cipher 1: </span><span class="si">{</span><span class="n">c1</span><span class="si">}</span><span class="s">, N1=</span><span class="si">{</span><span class="n">n1</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Cipher 2: </span><span class="si">{</span><span class="n">c2</span><span class="si">}</span><span class="s">, N2=</span><span class="si">{</span><span class="n">n2</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Cipher 3: </span><span class="si">{</span><span class="n">c3</span><span class="si">}</span><span class="s">, N3=</span><span class="si">{</span><span class="n">n3</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="se">\n</span><span class="s">We can solve M^e with CRT to get </span><span class="si">{</span><span class="n">res</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="n">val</span><span class="o">=</span><span class="n">libnum</span><span class="p">.</span><span class="n">nroot</span><span class="p">(</span><span class="n">res</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="se">\n</span><span class="s">If we assume e=3, we take the third root to get: </span><span class="si">{</span><span class="n">val</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Next we convert this integer to bytes, and display as a string."</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="se">\n</span><span class="s">Decipher: </span><span class="si">{</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">val</span><span class="p">)</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>

<p>We can run the python script and check the output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ &gt; python3 rsa_solver.py
Answer:

Cipher 1: 1585790700186...

We can solve M^e with CRT to get 76333906633...

If we assume e=3, we take the third root to get: 91391505128409176043...

Next we convert this integer to bytes, and display as a string.

Decipher: b'Head to the library. Upon entering, politely ask the librarian if they are aware of any extra documents refering to Madame De Maintenon.\x00\x00...
</code></pre></div></div>

<p>So finally it looks we obtain a bigger flag for the first flag we obtained, and it starts with the <em>“Head to the library”</em> that we found at the beginning, so it looks like the whole flag is: <em>“Head to the library. Upon entering, politely ask the librarian if they are aware of any extra documents refering to Madame De Maintenon.”</em></p>

<h5 id="solving-the-challenge">Solving the Challenge</h5>

<p>We have now everything we need for solving the challenge, we will write the next four flags in the correct order:</p>

<ul>
  <li>Head to the library. Upon entering, politely ask the librarian if they are aware of any extra documents refering to Madame De Maintenon.</li>
  <li>Check books on the next shelf</li>
  <li>Search the book for clues</li>
  <li>Turn over the page</li>
</ul>

<p>We will enter these flags, and we will see what we obtain.</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/33.png"><img src="/assets/images/hex-ray-challenge2/33.png" /></a>
</figure>

<p>It looks like this was the final part to solve the challenge, and we received a message with another big clue: 01000000110111000011011000000000. Also the challenge tells us to convert this big clue, with a union of the previous clues we found, and convert it into coordinates with 4 decimals each one like the next: <em>xx.xxxx, yy.yyyy</em>. Also those coordinates once they are hashed with MD5 we must obtain the next hash: <em>fe72f3730186f24d983a1c2ed1bc1da7</em>. The format for the binary numbers is IEEE-754 Floating Point.</p>

<p>If we use one converter website from the internet, we obtain the next two coordinates: <em>45.9238, 6.8815</em>, from the clues: <em>01000010001101111011001000000101, 01000000110111000011011000000000</em>.</p>

<p>We can now apply the MD5 hash:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ md5sum
45.9238, 06.8815
f3570036e3f0465cc7ac6abe4c5f4228
</code></pre></div></div>

<p>We can take these values and send them to <em>marketing@hex-rays.com</em>, because we have finished the challenge. Also we can go to google maps to look for the place pointed by the coordinates:</p>

<figure>
<a href="/assets/images/hex-ray-challenge2/34.png"><img src="/assets/images/hex-ray-challenge2/34.png" /></a>
</figure>

<p>And with this we finish the challenge, and the riddle has been solved!</p>

<figure>
<a href="https://media.tenor.com/Y_o7BH0XTgIAAAAC/jiu-clap.gif"><img src="https://media.tenor.com/Y_o7BH0XTgIAAAAC/jiu-clap.gif" /></a>
<figcaption>Detective Jiu solved successfully this case, congratulations!.</figcaption>
</figure>

<h3 id="acknowledgements">Acknowledgements</h3>

<p>I want to thank my friend Robert Yates who told me about this second challenge, and also helped me with some discussions about the analysis. I also want to thank the rest of the team from Quarkslab who are helping me to learn and improve a lot at work. All of you, thank you!</p>

<h3 id="full-text-from-the-challenge">Full text from the challenge</h3>

<p>Next I will copy paste the full text from the challenge with the correct answers:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You have heard rumours that the diary of Madame de Maintenon contained the secrets to a legendary plot.
Good luck on your journey to uncovering the truth behind this mystery!
You have heard that a rival historian recently discovered a copy of a chapter of the diary of Madame de Maintenon at the local library. But being unable to solve the mystery, returned it in frustration. Having long been fascinated by her history, you can't wait to investigate. What do you do?
Head to the library. Upon entering, politely ask the librarian if they are aware of any extra documents refering to Madame De Maintenon.

You locate the section of the library where the diary was rumoured to have been stored, but its place is empty. After a few minutes browsing, you find it! A single page, but one that holds the key to a fascinating mystery.

The page reads:
_______________
21 October 1684

Dear Diary,

Today, an unsettling discovery came my way. A letter, it was, with ominous tidings of a plot against our cherished Louis XIV. The message was unlike any other, its meaning hidden behind unfamiliar symbols.

Within the letter lay a clue, 01000010, a piece of the puzzle. It hinted at more secrets, and I felt compelled to uncover them. But where to find the next piece?

Yours in devotion,

Madame De Maintenon
_______________

The page was lying on the shelf in the open, maybe it fell from somewhere. You see a few more loose pages sticking out of some other books around you. What happened here?


What do you do?

Check books on the next shelf

What luck! While going through the books on the next shelf over, you find another page stuck under them, similarly weathered to the first one. The message is hard to decipher due to it's age, but after some careful analysis you manage to decode it.

It reads:
_______________
24 October 1684

Beloved Diary,
 
As I delved into the code, a new piece surfaced, 00110111. It whispered of hidden truths, yet it also hinted that there was more to uncover. The puzzle remained incomplete.

Yours eternally,

Madame De Maintenon
_______________

Another clue, what could it mean? And where are the rest?

What do you do?

Search the book for clues

From the lack of dust on the book you found, it's clear these were recently borrowed. Maybe the pages got mixed up with the books when being reshelved?

You look up the name of the last borrower, and look up what other books they may have checked out. There you find the diary records mentioned, as well as one other book. 
Finding that book on the shelves yields another page!

_______________
30 October 1684

Dearest Diary,

Another fragment emerged, 10110010. It was a step closer to the full picture, but it also held a hint. The rest of the location, it suggested, was not far away.

Yours eternally,

Madame De Maintenon
_______________



What do you do?

Turn over the page

Turning the page over, you find the final entry to the diary!

_______________
9 November 1684

Beloved Diary,

Today, the last piece fell into place, 00000101. With it came the realization that the remaining location lay elsewhere, a mystery yet to be unraveled. Our mission is clear, my dear diary; we must decipher the rest to protect our homeland.

Yours in devotion,

Madame de Maintenon
_______________

What does this mean? You've worked so hard but yet still don't have the information you seek? What now?
You have all four pages your rival claimed to have found, and yet are no closer to the truth.
After several hours of fruitlessly searching for meaning in the messages, you give up and turn to leave in defeat.


As you move to leave, the librarian comes running!

'I found this in the back room for you, it was a page we found lying around after procesing the most recent batch of new books but we weren't sure what it was for! But look at the signature!'

She hands you a fifth, almost completely blank new page. The aging of the paper looks near identical to the other four pages you found from the diary!

All the page says on it is:
_______________

The other key:

01000000110111000011011000000000

M d. M
_______________

You thank the librarian, and take your leave. You have much to think on. All these 1's and 0's, how do they encode the location of the final target???

#########################

Congratulations! If you've found all 5 pages of the diary you have everything you need! Convert the values you found into coordinates, (hint: IEEE-754 Floating Point), and send those coordinates in an email to marketing@hex-rays.com!
To locally verify your coordinates, the md5 of the coordinates, with 4 decimal places, (including potential leading zeros) in the form:
xx.xxxx, yy.yyyy
Has an md5 of fe72f3730186f24d983a1c2ed1bc1da7 when pasted as a 16 character string into https://www.md5hashgenerator.com/
</code></pre></div></div>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Reverse Engineering" /><category term="CTF" /><category term="Python" /><category term="ELF" /><category term="Linux" /><category term="Binary Analysis" /><category term="Binary Ninja" /><summary type="html"><![CDATA[Hex-rays has published a second CTF where we have to uncover the location of the traitors in the story of Madame de Maintenon (the IDA Lady)]]></summary></entry><entry><title type="html">Solving the hack.lu 2021 OLLVM Challenge with Triton</title><link href="https://fare9.github.io/symbolic%20execution/triton/hacklu-ollvm-triton/" rel="alternate" type="text/html" title="Solving the hack.lu 2021 OLLVM Challenge with Triton" /><published>2023-07-20T00:00:00+00:00</published><updated>2023-06-20T21:10:00+00:00</updated><id>https://fare9.github.io/symbolic%20execution/triton/hacklu-ollvm-triton</id><content type="html" xml:base="https://fare9.github.io/symbolic%20execution/triton/hacklu-ollvm-triton/"><![CDATA[<figure>
<a href="/assets/images/hacklu-ollvm/1.png"><img src="/assets/images/hacklu-ollvm/1.png" /></a>
<figcaption>Mirror, mirror on the wall whos the best kpop artist of this world...Oh no, this wasn't about that...</figcaption>
</figure>

<p>In continuation of our previous post on employing Triton for tackling challenges through symbolic execution and SMT Solving, this time we will take on an obfuscated challenge. Specifically, we’ll delve into a challenge from hack.lu 2021, which has already been conquered by Jonathan Salwan. The binary for this challenge can be accessed through this <a href="https://github.com/JonathanSalwan/Triton/blob/master/src/examples/python/ctf-writeups/hacklu-2021-ollvm/ollvm">link</a>.</p>

<p>In this post, our focus will be on understanding how the binary operates. While we won’t delve deeply into the mathematics involved in the challenge, we will learn how to solve it using <code class="language-plaintext highlighter-rouge">Z3</code>. Additionally, we will explore techniques to refine the final expression, and I’ll even share code from a blog where the ultimate expression is reversed.</p>

<p>For those interested, the necessary tools for this endeavor can be found here: <a href="https://triton-library.github.io/">Triton</a> and <a href="https://ghidra-sre.org/">Ghidra</a>.</p>

<h2 id="authors">Authors</h2>

<ul>
  <li>Eduardo Blazquez</li>
</ul>

<h2 id="the-challenge">The Challenge</h2>

<p>As mentioned in the previous post, we are dealing with an ELF file designed for a 64-bit architecture. This file is dynamically linked, stripped, and has a size of 495KB. Extracting this essential information is straightforward using a couple of Linux commands:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>file ollvm
<span class="go">ollvm: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, stripped
</span><span class="gp">$</span><span class="w"> </span><span class="nb">ls</span> <span class="nt">-lah</span> ollvm
<span class="go">-rwxrwx--- 1 symbolic symbolic 495K jul 15 17:23 ollvm
</span></code></pre></div></div>

<p>Once again, we are required to provide an argument to run the program. Alternatively, we can infer the necessary argument by executing the program without any input:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>./ollvm
<span class="go">Expected 1 parameters
</span></code></pre></div></div>

<p>Additionally, we discovered that this parameter must adhere to a specific format, as an input like <code class="language-plaintext highlighter-rouge">-h</code> to display help information does not function as intended.</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>./ollvm <span class="nt">-h</span>
<span class="go">Argument -h cannot be converted, exiting
</span></code></pre></div></div>

<p>As a last test, I will test the program with a couple of numbers and showcase the corresponding outputs. It turns out that when we provide numerical inputs, the program generates specific output values. Let’s examine the outputs in the following code snippet:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>./ollvm 1
<span class="go">Output: 9a1e0411b56b3264
</span><span class="gp">$</span><span class="w"> </span>./ollvm 2
<span class="go">Output: 8c1225f9a1f83264
</span><span class="gp">$</span><span class="w"> </span>./ollvm 0x20
<span class="go">Output: 88af74eef5623264
</span><span class="gp">$</span><span class="w"> </span>./ollvm 0b1100
<span class="go">Output: 953a4f4e4e823264
</span></code></pre></div></div>

<p>The only thing I’m doing is providing the program with a number in different formats (decimal, hexadecimal, and binary). As I observe, the program always returns an output of the same size, but each input number produces a different output. I suspect that the program uses some kind of hash function for each provided number.</p>

<p>This mathematical function can accept inputs of any size and, in theory, provides an output of a fixed size that varies for each unique input. Even a slight modification in the input can result in a significant change in the output.</p>

<figure>
<a href="/assets/images/hacklu-ollvm/2.png"><img src="/assets/images/hacklu-ollvm/2.png" /></a>
<figcaption>Graphical representation of a hash function (picture from: https://en.wikipedia.org/wiki/Cryptographic_hash_function).</figcaption>
</figure>

<p>Let’s explore the binary directly on Ghidra’s disassembler in order to discover how the binary works, and how we can proceed with the analysis for solving the challenge with Triton.</p>

<h3 id="analyzing-the-challenge-with-ghidra-and-a-little-of-gdb">Analyzing the Challenge with Ghidra (and a little of GDB)</h3>

<p>In the previous post, I explained the process of analyzing a binary using Ghidra. To begin, we create a Ghidra project, import the binary into the working area (just pressing <code class="language-plaintext highlighter-rouge">i</code>), and then open it with <code class="language-plaintext highlighter-rouge">CodeBrowser</code>. Subsequently, we instruct Ghidra to analyze the binary.</p>

<p>On the main disassembly screen, we can observe the disassembled code starting from the <code class="language-plaintext highlighter-rouge">entry</code> function, as indicated by the ELF header. As a reminder from the previous post, this function calls the <code class="language-plaintext highlighter-rouge">__libc_start_main</code> function from the <code class="language-plaintext highlighter-rouge">libc</code> library, with its first parameter stored in the <code class="language-plaintext highlighter-rouge">RDI</code> register—a pointer to the <code class="language-plaintext highlighter-rouge">main</code> function written by the developer. Therefore, in the next picture, the first parameter has already been renamed for clarity.</p>

<figure>
<a href="/assets/images/hacklu-ollvm/3.png"><img src="/assets/images/hacklu-ollvm/3.png" /></a>
<figcaption>entry function from ELF binary.</figcaption>
</figure>

<p>Next, I can directly navigate to the <code class="language-plaintext highlighter-rouge">main</code> function and format it to show the return type <code class="language-plaintext highlighter-rouge">int</code>, along with the parameters <code class="language-plaintext highlighter-rouge">(int argc, char **argv)</code>. This formatting will provide us with a clearer view in the decompiler:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/4.png"><img src="/assets/images/hacklu-ollvm/4.png" /></a>
<figcaption>Main function from the binary, giving the correct prototype, shows a better decompilation.</figcaption>
</figure>

<p>The first part of the code checks the <code class="language-plaintext highlighter-rouge">argc</code> value; if it’s equal to or greater than 2, we receive an error message indicating that only 1 parameter is expected. On the other hand, when a single parameter (a buffer of 64K) is provided, I’ve renamed it as <code class="language-plaintext highlighter-rouge">hash_results</code>, and it is set to 0. The code then calls a function, which I’ve renamed as <code class="language-plaintext highlighter-rouge">getUserIntValue</code>, passing <code class="language-plaintext highlighter-rouge">argv[1]</code> and the value <code class="language-plaintext highlighter-rouge">0x10</code> as parameters. The output from this function is stored in index 0x03 of the <code class="language-plaintext highlighter-rouge">hash_results</code> buffer, and I will show it in the next code snippet:</p>

<pre><code class="language-asm">00400899 8b 0d c1        MOV        ECX,dword ptr [double_index]                                = 00000003h
            a7 27 00
0040089f 48 89 04        MOV        qword ptr [0x67b280 + RCX*0x8]=&gt;user_value_storage,user_va  = ??
            cd 80 b2 
            67 00
</code></pre>

<p>Where <code class="language-plaintext highlighter-rouge">double_index</code> is equals to <code class="language-plaintext highlighter-rouge">0x3</code> and the value <code class="language-plaintext highlighter-rouge">0x67b280</code> is the <code class="language-plaintext highlighter-rouge">hash_results</code> buffer.</p>

<p>Finally, we encounter a somewhat unusual piece of code, where a value is retrieved, the pointer is advanced by 2, and then a function is indirectly called using the retrieved value as an index in an array of pointers, which I’ll refer to as <code class="language-plaintext highlighter-rouge">handlers</code>. To obtain the address of the handler, we simply retrieve the value of <code class="language-plaintext highlighter-rouge">handler_ptr</code>, multiply it by 8, and add it to the base address <code class="language-plaintext highlighter-rouge">0x0067a050</code>, where the handler pointers are located:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(0x1C9 * 8) + 0x0067a050 = 0x67ae98

# Pointerd memory
0067ae98 b0 36 46        addr       FUN_004636b0
            00 00 00 
            00 00
</code></pre></div></div>

<p>The first called handler is the function <code class="language-plaintext highlighter-rouge">FUN_004636b0</code>. We can be certain of this by using <code class="language-plaintext highlighter-rouge">gdb</code>, and in my case, I will utilize <code class="language-plaintext highlighter-rouge">gdb-gef</code>, which provides a better code view within the debugger. The <code class="language-plaintext highlighter-rouge">call</code> function resides at address <code class="language-plaintext highlighter-rouge">0x004008cc</code>. To set a breakpoint in <code class="language-plaintext highlighter-rouge">gdb</code>, use the command <code class="language-plaintext highlighter-rouge">b *0x004008cc</code>, and then execute the program with any input:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/5.png"><img src="/assets/images/hacklu-ollvm/5.png" /></a>
</figure>

<figure>
<a href="/assets/images/hacklu-ollvm/6.png"><img src="/assets/images/hacklu-ollvm/6.png" /></a>
</figure>

<figure>
<a href="/assets/images/hacklu-ollvm/7.png"><img src="/assets/images/hacklu-ollvm/7.png" /></a>
</figure>

<figure>
<a href="/assets/images/hacklu-ollvm/8.png"><img src="/assets/images/hacklu-ollvm/8.png" /></a>
</figure>

<p>In all the previous images, I demonstrated the process of obtaining the same address we obtained statically, but this time using the debugger. Later on, I will illustrate how we can achieve these values using Triton.</p>

<p>An essential point to note from the <code class="language-plaintext highlighter-rouge">main</code> function is that an index value is advanced by 2, as I mentioned earlier. This is interesting because the protection employs a structure containing various useful values for hash calculation and storing the resulting hash on each handler. However, before delving into that, let’s first take a closer look at the code for the initial handler. The code is obfuscated, and the resulting mathematical expression (which I’ll show with Triton later) will also be challenging to comprehend:</p>

<pre><code class="language-C++">void FirstHandler(void)
{
  ...
  const1 = *(long *)((long)&amp;FIRST_HANDLER.const1 + STRUCT_INDEX);
  const2 = *(ulong *)((long)&amp;FIRST_HANDLER.const2 + STRUCT_INDEX);
  hash_value1 = (&amp;hash_result)[*(ushort *)((long)&amp;FIRST_HANDLER.hash1 + STRUCT_INDEX)];
  hash_value2 = (&amp;hash_result)[*(ushort *)((long)&amp;FIRST_HANDLER.hash2 + STRUCT_INDEX)];
  auVar2._8_8_ = 0;
  auVar2._0_8_ = const2 &amp; 0xffffffff;
  uVar18 = SUB168((ZEXT816(0) &lt;&lt; 0x40 | ZEXT816(0x11a9b37518b9d587)) % auVar2,0);
  bVar9 = (byte)hash_value2 &amp; 0x3f;
  lVar19 = hash_value2 + const1;
  if (const2 != 0) {
    bVar9 = 0;
    lVar19 = 0;
  }
  bVar10 = const1 == 0 || const2 == 0;
  uVar25 = (uint)bVar10;
  auVar3._8_8_ = 0;
  auVar3._0_8_ = const2 &amp; 0xffffffff;
  auVar3 = (ZEXT816(0) &lt;&lt; 0x40 | ZEXT816(0x17e87cc7bd2f0913)) % auVar3;
  lVar20 = auVar3._0_8_;
  uVar1 = lVar20 - 1;
  uVar11 = auVar3._0_4_;
  uVar26 = (ulong)(((int)uVar1 * 2 ^ 0xfffffffdU) &amp; uVar11) | 2;
  uVar23 = 1 - uVar26 ^ lVar20 + 0x7fffffffffffffffU;
  auVar4._8_8_ = 0;
  auVar4._0_8_ = (const2 | 0xffffffff00000000) + 0x100000000;
  uVar5 = (long)uVar23 &gt;&gt; 0x3f;
  uVar14 = -uVar5;
  uVar22 = ((~(-(int)const1 | ~uVar25) | uVar25) &amp; uVar25) * const2 + hash_value1;
  iVar12 = (uint)(byte)(const2 &gt;&gt; 0x38) * 0x41225f1;
  uVar16 = const2 &gt;&gt; 0x20 &amp; 0xff;
  uVar25 = (uint)uVar16;
  uVar13 = (iVar12 - (uVar25 * uVar25 &amp; 2 ^ uVar25)) * (iVar12 - uVar25);
  uVar25 = uVar13 + 0xfe;
  uVar8 = (const2 &amp; 0xffffffff) &gt;&gt; 0x18;
  uVar29 = (uint)((const2 &amp; 0xffffffff) &gt;&gt; 0x18);
  uVar6 = -((ulong)(~(uint)(const2 &gt;&gt; 0x20) &amp; uVar29 &amp; uVar13 ^ ((uVar25 | 2) &amp; uVar25) + 2 &amp; uVar29
                   ) * (-hash_value1 - const1));
  uVar34 = const2 &gt;&gt; 0x10 &amp; 0xffff;
  uVar32 = const2 &gt;&gt; 0x20 &amp; 0xffff;
  uVar7 = const2;
  if (hash_value1 == 0) {
    uVar7 = 0;
  }
  uVar15 = 0;
  if (bVar10) {
    uVar15 = const2;
  }
  uVar21 = (const2 &gt;&gt; 0x38) - 0xf6 &amp; 0xf4 - (const2 &gt;&gt; 0x38);
  uVar28 = const2 &amp; 0xff;
  uVar31 = const2 &gt;&gt; 0x10 &amp; 0xff;
  uVar30 = 0x86 - uVar31 &amp; uVar31 - 0x88;
  uVar27 = uVar16 - 0x5c &amp; 0x5a - uVar16 &amp; uVar8 - 0x83 &amp; 0x81 - uVar8;
  uVar8 = const2 &gt;&gt; 0x28 &amp; 0xff;
  uVar16 = uVar8 - 0x14 &amp; 0x12 - uVar8;
  uVar8 = const2 &gt;&gt; 0x30 &amp; 0xff;
  uVar8 = uVar8 - 0xac &amp; 0xaa - uVar8;
  uVar35 = ~(-(ulong)((uint)(2L &lt;&lt; ((byte)(uVar28 - 0x44) &amp; 0x3f)) &amp; 1) | uVar28 - 0x44) &amp;
           uVar28 - 0x45;
  uVar24 = const2 &gt;&gt; 8 &amp; 0xff;
  uVar17 = uVar16 &amp; uVar8 &amp; uVar27;
  uVar33 = uVar24 - 0x3b &amp; 0x39 - uVar24;
  uVar28 = 0x43 - uVar28 &amp; uVar28 - 0x45 &amp; uVar33;
  lVar20 = -((long)(uVar8 &amp; uVar30 &amp; uVar28 &amp; uVar31 + 0x7fffffffffffff79 &amp; uVar16 &amp; uVar27) &gt;&gt; 0x3f
            );
  uVar25 = (uint)(uVar17 &gt;&gt; 0x20) &amp; (uint)(uVar30 &gt;&gt; 0x20);
  uVar16 = (ulong)(((uint)(uVar28 &gt;&gt; 0x20) &amp; uVar25) &gt;&gt; 0x1f);
  uVar8 = (lVar20 - ((long)(uVar33 &amp; uVar30 &amp; uVar17 &amp; uVar35 &amp; uVar21) &gt;&gt; 0x3f)) - uVar16;
  (&amp;hash_result)[*(ushort *)((long)&amp;FIRST_HANDLER.result_hash + STRUCT_INDEX)] =
       (((((long)(-3 - ((uVar18 | 0xfffffffffffffffe) &amp; ~(uVar18 + 1 &amp; (uVar18 | 0x1fffffffe)))) &gt;&gt;
           0x3f &amp; hash_value2 &lt;&lt; bVar9) + lVar20 + 1) - uVar16) -
       (ulong)((((uint)(uVar24 - 0x3a &gt;&gt; 0x20) | (uint)(uVar24 - 0x3b &gt;&gt; 0x20)) &amp;
                (uint)(0x39 - uVar24 &gt;&gt; 0x20) &amp; (uint)(uVar35 &gt;&gt; 0x20) &amp; uVar25) &gt;&gt; 0x1f) *
       ((long)uVar21 &gt;&gt; 0x3f)) + ~uVar8 + (const1 * const2 &amp; const2) * uVar8 +
       ((((uVar15 + hash_value1) - uVar22) + uVar14 | uVar14) * uVar22 +
        ((long)(uVar32 - 0x2163 &amp; 0x2161 - uVar32 &amp;
                (const2 &amp; 0xffff) - 0xa2e7 &amp; 0xa2e5 - (const2 &amp; 0xffff) &amp; (const2 &gt;&gt; 0x30) - 0xe63 &amp;
                uVar34 - 0x7fdf &amp; 0x7fdd - uVar34 &amp;
               0xe61 - (ulong)((~(uint)(2L &lt;&lt; ((byte)(const2 &gt;&gt; 0x30) &amp; 0x3f)) | 0xfffffffd) &amp;
                              (uint)(ushort)(const2 &gt;&gt; 0x30))) &gt;&gt; 0x3f &amp; uVar7 + lVar19) +
        ((uVar6 ^ 2 | uVar6) &amp; uVar6) ^
       -(uVar5 &amp; uVar22 &amp;
        ~(-((long)((uVar26 - ((ulong)((SUB164((ZEXT816(0) &lt;&lt; 0x40 | ZEXT816(0x17e87cc7bd2f0913)) %
                                              auVar4,0) * 2 - 2U ^ 0xfffffffd) &amp; uVar11) | 2)) - 1 &amp;
                   uVar1 | uVar23) &gt;&gt; 0x3f) * uVar22)));
  next_handler_index = (short *)((long)&amp;FIRST_HANDLER.next_handler + STRUCT_INDEX);
  STRUCT_INDEX = STRUCT_INDEX + 24;
  (*(code *)(&amp;Handlers)[*next_handler_index])(&amp;hash_result);
  return;
}
</code></pre>

<p>As observed, the expression employs various constants alongside arithmetic and boolean expressions, collectively referred to as Mixed Boolean-Arithmetic (MBA) expressions. These expressions are particularly effective for obfuscating mathematical expressions that would otherwise be much simpler. For further understanding, I recommend exploring theses such as <a href="https://theses.hal.science/tel-01623849/document">Obfuscation with Mixed Boolean-Arithmetic Expressions: reconstruction, analysis, and simplification tools</a> by Ninon Eyrolles or <a href="https://openaccess.uoc.edu/bitstream/10609/146182/8/arnaugamezFMDP0622report.pdf">Analysis and applications of orthogonal approaches to simplify Mixed Boolean-Arithmetic expressions</a> by Arnau Gamez.</p>

<p>Since the expressions will be solved using <code class="language-plaintext highlighter-rouge">Z3</code>, I will focus on other aspects of the obfuscation. As evident here, the call is an indirect call to the list of handlers, which entirely disrupts the call graph.</p>

<figure>
<a href="/assets/images/hacklu-ollvm/CG.png"><img src="/assets/images/hacklu-ollvm/CG.png" /></a>
<figcaption>Representation of a Call Graph and a broken Call Graph.</figcaption>
</figure>

<p>As I previously said, we observed that a pointer was advanced 2 bytes, and in different parts of the code we observe access to an structure:</p>

<pre><code class="language-C++">const1 = *(long *)((long)&amp;FIRST_HANDLER.const1 + STRUCT_INDEX);
const2 = *(ulong *)((long)&amp;FIRST_HANDLER.const2 + STRUCT_INDEX);
hash_value1 = (&amp;hash_result)[*(ushort *)((long)&amp;FIRST_HANDLER.hash1 + STRUCT_INDEX)];
hash_value2 = (&amp;hash_result)[*(ushort *)((long)&amp;FIRST_HANDLER.hash2 + STRUCT_INDEX)];
</code></pre>

<pre><code class="language-C++">(&amp;hash_result)[*(ushort *)((long)&amp;FIRST_HANDLER.result_hash + STRUCT_INDEX)] =
    (((((long)(-3 - ((uVar18 | 0xfffffffffffffffe) &amp; ~(uVar18 + 1 &amp; (uVar18 | 0x1fffffffe)))) &gt;&gt;
        0x3f &amp; hash_value2 &lt;&lt; bVar9) + lVar20 + 1) - uVar16) -
    (ulong)((((uint)(uVar24 - 0x3a &gt;&gt; 0x20) | (uint)(uVar24 - 0x3b &gt;&gt; 0x20)) &amp;
            (uint)(0x39 - uVar24 &gt;&gt; 0x20) &amp; (uint)(uVar35 &gt;&gt; 0x20) &amp; uVar25) &gt;&gt; 0x1f) *
    ((long)uVar21 &gt;&gt; 0x3f)) + ~uVar8 + (const1 * const2 &amp; const2) * uVar8 +
    ((((uVar15 + hash_value1) - uVar22) + uVar14 | uVar14) * uVar22 +
    ((long)(uVar32 - 0x2163 &amp; 0x2161 - uVar32 &amp;
            (const2 &amp; 0xffff) - 0xa2e7 &amp; 0xa2e5 - (const2 &amp; 0xffff) &amp; (const2 &gt;&gt; 0x30) - 0xe63 &amp;
            uVar34 - 0x7fdf &amp; 0x7fdd - uVar34 &amp;
            0xe61 - (ulong)((~(uint)(2L &lt;&lt; ((byte)(const2 &gt;&gt; 0x30) &amp; 0x3f)) | 0xfffffffd) &amp;
                            (uint)(ushort)(const2 &gt;&gt; 0x30))) &gt;&gt; 0x3f &amp; uVar7 + lVar19) +
    ((uVar6 ^ 2 | uVar6) &amp; uVar6) ^
    -(uVar5 &amp; uVar22 &amp;
    ~(-((long)((uVar26 - ((ulong)((SUB164((ZEXT816(0) &lt;&lt; 0x40 | ZEXT816(0x17e87cc7bd2f0913)) %
                                            auVar4,0) * 2 - 2U ^ 0xfffffffd) &amp; uVar11) | 2)) - 1 &amp;
                uVar1 | uVar23) &gt;&gt; 0x3f) * uVar22)));
</code></pre>

<pre><code class="language-C++">next_handler_index = (short *)((long)&amp;FIRST_HANDLER.next_handler + STRUCT_INDEX);
STRUCT_INDEX = STRUCT_INDEX + 24;
(*(code *)(&amp;Handlers)[*next_handler_index])(&amp;hash_result);
</code></pre>

<p>Each part of the code accesses a specific portion of the structure. Initially, two constants of 8 bytes each are accessed and stored in local variables. Next, two hash values from the <code class="language-plaintext highlighter-rouge">hash_result</code> table are retrieved using indices from the structure. Once the final hash is calculated, it is stored in the index pointed to by the <code class="language-plaintext highlighter-rouge">result_hash</code> value within the structure. Finally, towards the end of the code, there is access to another field that points to the next handler to be executed.</p>

<p>To create the structure in Ghidra, follow these steps. First, navigate to the <em>data type manager</em> located at the bottom-left corner of the <em>CodeBrowser</em>:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/9.png"><img src="/assets/images/hacklu-ollvm/9.png" /></a>
</figure>

<p>We will right click in the name of our file (in this case <code class="language-plaintext highlighter-rouge">ollvm</code>), and we will see the next options:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/10.png"><img src="/assets/images/hacklu-ollvm/10.png" /></a>
</figure>

<p>We just choose to create a <code class="language-plaintext highlighter-rouge">new-&gt;structure</code> and we will see a screen like the next:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/11.png"><img src="/assets/images/hacklu-ollvm/11.png" /></a>
</figure>

<p>While I won’t provide a detailed explanation of how I obtained each part of the structure, I will highlight some aspects of the code that will aid in understanding how it’s possible to extract each field from the structure:</p>

<pre><code class="language-asm">        assume RDX = 0x2
004636ba 48 8b 15        MOV        RDX,qword ptr [STRUCT_INDEX]                                = ??
            c7 7b 21 00
004636c1 0f b7 82        MOVZX      EAX,word ptr [RDX + FIRST_HANDLER]
            64 b0 67 00
004636c8 48 89 44        MOV        qword ptr [RSP + first_value],RAX
            24 f0
004636cd 0f b7 82        MOVZX      EAX,word ptr [RDX + HANDLER_STRUCTURE]
            66 b0 67 00
004636d4 0f b7 8a        MOVZX      ECX,word ptr [RDX + CONST1]
            68 b0 67 00
004636db 48 8b ba        MOV        RDI,qword ptr [RDX + QWORD_CONST1]
            6a b0 67 00
004636e2 48 89 54        MOV        qword ptr [RSP + first_constant],RDX
            24 f8
004636e7 48 8b 9a        MOV        RBX,qword ptr [RDX + QWORD_CONST2]
            72 b0 67 00
004636ee 4c 8b 3c        MOV        R15,qword ptr [hash_result + RAX*0x8]                       = ??
            c5 80 b2 
            67 00
004636f6 48 8b 34        MOV        RSI,qword ptr [hash_result + RCX*0x8]                       = ??
            cd 80 b2 
            67 00
</code></pre>

<p>If we recall from the <code class="language-plaintext highlighter-rouge">main</code> function, <code class="language-plaintext highlighter-rouge">STRUCT_INDEX</code> was set to 2. Next, we need to access the <code class="language-plaintext highlighter-rouge">FIRST_HANDLER</code> memory, add 2 to the address, and inspect the memory values using the debugger. Let’s observe the accessed values:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/12.png"><img src="/assets/images/hacklu-ollvm/12.png" /></a>
</figure>

<p>The values obtained are <code class="language-plaintext highlighter-rouge">0x2</code> and <code class="language-plaintext highlighter-rouge">0x3</code> for the hash index, and <code class="language-plaintext highlighter-rouge">0x4ddb14ee5c8771c5</code> and <code class="language-plaintext highlighter-rouge">0x56426f353ff403c2</code> for the constants. By searching for these results in the memory, we can locate the beginning of the structure. Additionally, there are two more values: <code class="language-plaintext highlighter-rouge">result_hash</code> with the value <code class="language-plaintext highlighter-rouge">0x2</code> and the value <code class="language-plaintext highlighter-rouge">0x1ea</code>, which represents the index to the next handler. When we combine all these fields and assign a name, we define the next structure:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/13.png"><img src="/assets/images/hacklu-ollvm/13.png" /></a>
</figure>

<p>In C the structure would be the next:</p>

<pre><code class="language-C">struct handler_struct {
    word result_hash;
    word hash1;
    word hash2;
    qword const1;
    qword const2;
    word next_handler;
};
</code></pre>

<p>Each time the program completes a handler, it updates the <code class="language-plaintext highlighter-rouge">STRUCT_INDEX</code> value by adding 24 bytes, which precisely matches the size of this structure. As a result, we have a chain of structures, with one for each handler, to store values and point to the next handler. Let’s visualize this chain:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/hashes.png"><img src="/assets/images/hacklu-ollvm/hashes.png" /></a>
<figcaption>Connection between handlers and structures.</figcaption>
</figure>

<p>Following the process we followed before, we can calculate the next handlers, we can make use of the previous structure:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(0x1ea * 0x8) + 0x0067a050 = 0x0067afa0

0067afa0 f0 b1 46        addr       FUN_0046b1f0
            00 00 00 
            00 00

(0x49 * 0x8) + 0x0067a050 = 0x0067a298

0067a298 60 fa 40        addr       FUN_0040fa60
            00 00 00 
            00 00
...
</code></pre></div></div>

<p>But we will extract this data using Triton for each one of the handlers the program executes.</p>

<h3 id="analyzing-the-binary-with-triton">Analyzing the binary with Triton</h3>

<p>As a reminder from the previous post, when using Triton, we needed to perform several steps before emulating the binary. Firstly, we had to read the file, load it into memory following the sections from the ELF Binary, and apply some relocations before we could begin working with the binary. We achieved this using the <code class="language-plaintext highlighter-rouge">Lief</code> library. As we did in the previous post, the following code demonstrates these steps:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">triton</span> <span class="kn">import</span> <span class="o">*</span>

<span class="kn">import</span> <span class="nn">string</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">lief</span>

<span class="c1"># Target binary
</span><span class="n">TARGET</span> <span class="o">=</span> <span class="s">"./ollvm"</span>


<span class="c1"># Global settings
</span><span class="n">SYMBOLIC</span> <span class="o">=</span> <span class="bp">True</span>
<span class="n">CONCRETE</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">SYMBOLIC</span>

<span class="c1"># Memory mapping
</span><span class="n">BASE_PLT</span> <span class="o">=</span> <span class="mh">0x10000000</span>
<span class="n">BASE_ARGV</span> <span class="o">=</span> <span class="mh">0x20000000</span>
<span class="n">BASE_STACK</span> <span class="o">=</span> <span class="mh">0x9ffffff0</span>
<span class="n">ERRNO</span> <span class="o">=</span> <span class="mh">0xa0000000</span>

<span class="p">...</span>

<span class="k">def</span> <span class="nf">loadBinary</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">,</span> <span class="n">lief_binary</span><span class="p">):</span>
    <span class="s">'''
    Use Lief parser in order to retrieve
    information of the binary, and load it
    in Triton's memory.

    :param triton_ctx: context where triton stores all the information.
    :param lief_binary: parser of lief with information about the headers.
    '''</span>
    <span class="n">phdrs</span> <span class="o">=</span> <span class="n">lief_binary</span><span class="p">.</span><span class="n">segments</span>
    <span class="k">for</span> <span class="n">phdr</span> <span class="ow">in</span> <span class="n">phdrs</span><span class="p">:</span>
        <span class="n">size</span> <span class="o">=</span> <span class="n">phdr</span><span class="p">.</span><span class="n">physical_size</span>
        <span class="n">vaddr</span> <span class="o">=</span> <span class="n">phdr</span><span class="p">.</span><span class="n">virtual_address</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[+] Loading 0x%06x - 0x%06x"</span> <span class="o">%</span> <span class="p">(</span><span class="n">vaddr</span><span class="p">,</span> <span class="n">vaddr</span><span class="o">+</span><span class="n">size</span><span class="p">))</span>
        <span class="n">triton_ctx</span><span class="p">.</span><span class="n">setConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">vaddr</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">phdr</span><span class="p">.</span><span class="n">content</span><span class="p">))</span>
    <span class="k">return</span>


<span class="k">def</span> <span class="nf">makeRelocation</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">binary</span><span class="p">):</span>
    <span class="s">'''
    Extract the addresses from the PLT, these will be used
    to retrieve the addressed and hook the functions once we have to run them.

    :param ctx: triton context for the emulation.
    :param binary: lief binary parser.
    '''</span>
    <span class="c1"># Setup plt
</span>    <span class="k">print</span><span class="p">(</span><span class="s">"[+] Applying relocations and extracting the addresses for the external functions"</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">pltIndex</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">customRelocation</span><span class="p">)):</span>
        <span class="n">customRelocation</span><span class="p">[</span><span class="n">pltIndex</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">BASE_PLT</span> <span class="o">+</span> <span class="n">pltIndex</span>

    <span class="n">relocations</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">binary</span><span class="p">.</span><span class="n">pltgot_relocations</span><span class="p">]</span>
    <span class="n">relocations</span><span class="p">.</span><span class="n">extend</span><span class="p">([</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">binary</span><span class="p">.</span><span class="n">dynamic_relocations</span><span class="p">])</span>

    <span class="c1"># Perform our own relocations
</span>    <span class="k">for</span> <span class="n">rel</span> <span class="ow">in</span> <span class="n">relocations</span><span class="p">:</span>
        <span class="n">symbolName</span> <span class="o">=</span> <span class="n">rel</span><span class="p">.</span><span class="n">symbol</span><span class="p">.</span><span class="n">name</span>
        <span class="n">symbolRelo</span> <span class="o">=</span> <span class="n">rel</span><span class="p">.</span><span class="n">address</span>
        <span class="k">for</span> <span class="n">crel</span> <span class="ow">in</span> <span class="n">customRelocation</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">symbolName</span> <span class="o">==</span> <span class="n">crel</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">'[+] Init PLT for: %s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">symbolName</span><span class="p">))</span>
                <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">MemoryAccess</span><span class="p">(</span>
                    <span class="n">symbolRelo</span><span class="p">,</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">),</span> <span class="n">crel</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
                <span class="k">break</span>
    <span class="k">return</span>

</code></pre></div></div>

<p>Furthermore, we require a hooking handler that will execute each emulated API and apply symbolization of the return register if a value is provided:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">hookingHandler</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    In case one of the run address is one from
    the emulated functions, just call it and
    get the result, check if it's needed to symbolize
    the output register.

    :param ctx: Triton's context for emulation.
    '''</span>
    <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">rel</span> <span class="ow">in</span> <span class="n">customRelocation</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">rel</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">pc</span><span class="p">:</span>
            <span class="c1"># Emulate the routine and the return value
</span>            <span class="n">state</span><span class="p">,</span> <span class="n">ret_value</span> <span class="o">=</span> <span class="n">rel</span><span class="p">[</span><span class="mi">1</span><span class="p">](</span><span class="n">ctx</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">ret_value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
                <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rax</span><span class="p">,</span> <span class="n">ret_value</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">state</span> <span class="ow">is</span> <span class="n">SYMBOLIC</span><span class="p">:</span>
                    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'[+] Symbolizing the return value'</span><span class="p">)</span>
                    <span class="n">ctx</span><span class="p">.</span><span class="n">symbolizeRegister</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rax</span><span class="p">)</span>
            <span class="c1"># Get the return address
</span>            <span class="n">ret_addr</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteMemoryValue</span><span class="p">(</span><span class="n">MemoryAccess</span><span class="p">(</span>
                <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">),</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">))</span>
            <span class="c1"># Hijack RIP to skip the call
</span>            <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">,</span> <span class="n">ret_addr</span><span class="p">)</span>
            <span class="c1"># Restore RSP (simulate the ret)
</span>            <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span>
                <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">)</span><span class="o">+</span><span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">)</span>
    <span class="k">return</span>
</code></pre></div></div>

<p>In this instance, I have implemented two functions: <code class="language-plaintext highlighter-rouge">pre_execution</code> and <code class="language-plaintext highlighter-rouge">post_execution</code>, which will be invoked from the <code class="language-plaintext highlighter-rouge">emulate</code> function—right before and right after the call to <code class="language-plaintext highlighter-rouge">processing</code> from the <code class="language-plaintext highlighter-rouge">TritonContext</code> object. These functions include several parameters that prove useful for the analysis:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">pre_execution</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Code to call before processing an instruction
    '''</span>
    <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">pc</span>

<span class="k">def</span> <span class="nf">post_execution</span><span class="p">(</span><span class="n">previous_pc</span><span class="p">,</span> <span class="n">instruction</span><span class="p">,</span> <span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Code to call after processing an instruction
    '''</span>
    <span class="k">pass</span>

<span class="k">def</span> <span class="nf">emulate</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">pc</span><span class="p">):</span>
    <span class="s">'''
    Emulation function, go over each instruction applying all the
    symbolic execution to registers and memory.

    :param ctx: Triton context to apply symbolic execution.
    :param pc: the program counter value where to start and continue.
    :valut_to_check: value to check once we wants to stop the execution.
    '''</span>

    <span class="c1"># emulation loop
</span>    <span class="k">while</span> <span class="n">pc</span><span class="p">:</span>

        <span class="c1"># print("[-] Running instruction at address: 0x%08X" % (pc))
</span>
        <span class="n">opcodes</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
        <span class="n">instruction</span> <span class="o">=</span> <span class="n">Instruction</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="n">opcodes</span><span class="p">)</span>

        <span class="c1"># if we want to bypass code, do it
</span>        <span class="c1"># in this function
</span>        <span class="n">pc</span> <span class="o">=</span> <span class="n">pre_execution</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>

        <span class="c1"># process the instruction
</span>        <span class="n">ret</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">processing</span><span class="p">(</span><span class="n">instruction</span><span class="p">)</span>
        <span class="c1"># if HALT, finish the execution
</span>        <span class="k">if</span> <span class="n">instruction</span><span class="p">.</span><span class="n">getType</span><span class="p">()</span> <span class="o">==</span> <span class="n">OPCODE</span><span class="p">.</span><span class="n">X86</span><span class="p">.</span><span class="n">HLT</span><span class="p">:</span>
            <span class="k">break</span>

        <span class="c1"># all the code after processing, goes here
</span>        <span class="n">post_execution</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="n">instruction</span><span class="p">,</span> <span class="n">ctx</span><span class="p">)</span>

        <span class="c1"># apply one of the handlers that are not provided by
</span>        <span class="c1"># Triton
</span>        <span class="n">hookingHandler</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>

        <span class="c1"># Next
</span>        <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
</code></pre></div></div>

<p>With this structure in place, we have the ability to modify the instruction flow, allowing us to run our analysis immediately after the processing of each instruction. In the case of this binary, our primary focus will be on the <code class="language-plaintext highlighter-rouge">post_execution</code> function.</p>

<h4 id="first-of-all-the-hooks">First of all, the hooks</h4>

<p>Given that there are several API functions in this binary, we need to provide handlers for them. The most critical function is the one called at the start of the binary, <code class="language-plaintext highlighter-rouge">__libc_start_main</code>. Additionally, we have other functions such as <code class="language-plaintext highlighter-rouge">memset</code>, <code class="language-plaintext highlighter-rouge">__errno_location</code>, <code class="language-plaintext highlighter-rouge">strtoul</code>, and <code class="language-plaintext highlighter-rouge">printf</code>. For the first function, we will write the arguments to the program, while for the others, we will simply “emulate” their behavior. However, <code class="language-plaintext highlighter-rouge">strtoul</code> requires special attention as it receives our first argument and returns the <code class="language-plaintext highlighter-rouge">unsigned long</code> number version. This value serves as input for the hash function, and here we will symbolize the output of <code class="language-plaintext highlighter-rouge">strtoul</code> to ultimately obtain the expression required to solve the challenge. Below, you can find the code for these hooks:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Hook for memset set concrete memory value
    '''</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'[+] memset hooked'</span><span class="p">)</span>
    <span class="n">ptr</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">)</span>
    <span class="n">size</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdx</span><span class="p">)</span>
    <span class="n">value</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">size</span><span class="p">):</span>
        <span class="n">memset_mem_value</span> <span class="o">=</span> <span class="n">MemoryAccess</span><span class="p">(</span><span class="n">ptr</span><span class="o">+</span><span class="n">i</span><span class="p">,</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">BYTE</span><span class="p">)</span>
        <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">memset_mem_value</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>

    <span class="k">return</span> <span class="p">(</span><span class="n">CONCRETE</span><span class="p">,</span> <span class="n">size</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">__errno_location</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Return the address of ERRNO value
    '''</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'[+] __errno_location hooked'</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">CONCRETE</span><span class="p">,</span> <span class="n">ERRNO</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">strtoul</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Hook for strtoul
    '''</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'[+] strtoul hooked'</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">SYMBOLIC</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="s">"0xdeadbeef"</span><span class="p">,</span> <span class="mi">16</span><span class="p">))</span>


<span class="k">def</span> <span class="nf">libc_start_main</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Emulation of libc start, here we will set the
    arguments giving them an address in memory and
    copying the values into that memory.
    '''</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'[+] __libc_start_main hooked'</span><span class="p">)</span>

    <span class="c1"># Get arguments
</span>    <span class="n">main</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">)</span>

    <span class="c1"># Push the return value to jump into the main() function
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span>
        <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">)</span><span class="o">-</span><span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">)</span>

    <span class="c1"># set as return value the address of main
</span>    <span class="c1"># avoid all the libc stuff
</span>    <span class="n">ret2main</span> <span class="o">=</span> <span class="n">MemoryAccess</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span>
        <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">),</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">)</span>
    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">ret2main</span><span class="p">,</span> <span class="n">main</span><span class="p">)</span>

    <span class="c1"># Setup argc / argv
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">concretizeRegister</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">)</span>
    <span class="n">ctx</span><span class="p">.</span><span class="n">concretizeRegister</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">)</span>

    <span class="c1"># here write all the needed arguments
</span>    <span class="n">argvs</span> <span class="o">=</span> <span class="p">[</span>
        <span class="nb">bytes</span><span class="p">(</span><span class="n">TARGET</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)),</span>  <span class="c1"># argv[0]
</span>        <span class="sa">b</span><span class="s">'1000000'</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'</span><span class="se">\00</span><span class="s">'</span>
    <span class="p">]</span>

    <span class="c1"># Define argc / argv
</span>    <span class="n">base</span> <span class="o">=</span> <span class="n">BASE_ARGV</span>
    <span class="n">addrs</span> <span class="o">=</span> <span class="nb">list</span><span class="p">()</span>

    <span class="c1"># create the arguments
</span>    <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">argv</span> <span class="ow">in</span> <span class="n">argvs</span><span class="p">:</span>
        <span class="n">addrs</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
        <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">argv</span><span class="o">+</span><span class="sa">b</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">)</span>
        <span class="n">base</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">argv</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span>
        <span class="k">print</span><span class="p">(</span><span class="s">'[+] argv[%d] = %s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">argv</span><span class="p">))</span>
        <span class="n">index</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="c1"># set the pointer to the arguments
</span>    <span class="n">argc</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">argvs</span><span class="p">)</span>
    <span class="n">argv</span> <span class="o">=</span> <span class="n">base</span>
    <span class="k">for</span> <span class="n">addr</span> <span class="ow">in</span> <span class="n">addrs</span><span class="p">:</span>
        <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">MemoryAccess</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">),</span> <span class="n">addr</span><span class="p">)</span>
        <span class="n">base</span> <span class="o">+=</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span>

    <span class="c1"># finally set RDI and RSI values
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">,</span> <span class="n">argc</span><span class="p">)</span>
    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">,</span> <span class="n">argv</span><span class="p">)</span>

    <span class="k">return</span> <span class="p">(</span><span class="n">CONCRETE</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">printf</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Hook for printf
    '''</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[+] printf Hooked"</span><span class="p">)</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Output: %lx"</span> <span class="o">%</span> <span class="p">(</span><span class="n">output</span><span class="p">))</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">CONCRETE</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>


<span class="c1"># this structure will be useful during emulation
# whenever the emulation jumps to any of the functions
# from the first field, use the second fields as hook.
</span><span class="n">customRelocation</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">[</span><span class="s">'__libc_start_main'</span><span class="p">,</span> <span class="n">libc_start_main</span><span class="p">,</span> <span class="bp">None</span><span class="p">],</span>
    <span class="p">[</span><span class="s">'memset'</span><span class="p">,</span> <span class="n">memset</span><span class="p">,</span> <span class="bp">None</span><span class="p">],</span>
    <span class="p">[</span><span class="s">'__errno_location'</span><span class="p">,</span> <span class="n">__errno_location</span><span class="p">,</span> <span class="bp">None</span><span class="p">],</span>
    <span class="p">[</span><span class="s">'strtoul'</span><span class="p">,</span> <span class="n">strtoul</span><span class="p">,</span> <span class="bp">None</span><span class="p">],</span>
    <span class="p">[</span><span class="s">'printf'</span><span class="p">,</span> <span class="n">printf</span><span class="p">,</span> <span class="bp">None</span><span class="p">]</span>
<span class="p">]</span>
</code></pre></div></div>

<p>As evident from the previous snippet, symbolizing the return value is a straightforward process, as shown in the following code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">strtoul</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Hook for strtoul
    '''</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'[+] strtoul hooked'</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">SYMBOLIC</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="s">"0xdeadbeef"</span><span class="p">,</span> <span class="mi">16</span><span class="p">))</span>
</code></pre></div></div>

<p>In the <code class="language-plaintext highlighter-rouge">hookingHandler</code> function, we will set the <code class="language-plaintext highlighter-rouge">RAX</code> register value as symbolic, and the returned value will be the concrete value from that register. In this case, the value will be <code class="language-plaintext highlighter-rouge">0xdeadbeef</code>.</p>

<h4 id="retrieving-the-addresses-of-the-handler">Retrieving the addresses of the handler</h4>

<p>To retrieve the addresses of the handlers executed by the program, we have two approaches. As we previously saw, we can do this manually using the values from the structure or set breakpoints in a debugger. The first handler is executed using a <code class="language-plaintext highlighter-rouge">call</code> instruction, and the rest are executed directly with a <code class="language-plaintext highlighter-rouge">jmp rax</code> instruction. In the <code class="language-plaintext highlighter-rouge">post_execution</code> function, as mentioned earlier, I will write the code to extract the value for the <code class="language-plaintext highlighter-rouge">call</code> instruction, and for the <code class="language-plaintext highlighter-rouge">jmp rax</code> instruction, I will search for it dynamically during runtime.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">post_execution</span><span class="p">(</span><span class="n">previous_pc</span><span class="p">,</span> <span class="n">instruction</span><span class="p">,</span> <span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Code to call after processing an instruction
    '''</span>
    <span class="c1"># to get the first handler
</span>    <span class="k">if</span> <span class="n">previous_pc</span> <span class="o">==</span> <span class="mh">0x004008cc</span><span class="p">:</span>
        <span class="n">current_pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[+] Call to first VM_Handler, at address: 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">current_pc</span><span class="p">))</span>
        <span class="nb">input</span><span class="p">(</span><span class="s">"ENTER"</span><span class="p">)</span>
    <span class="c1"># check next handlers!
</span>    <span class="k">if</span> <span class="s">"jmp rax"</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">instruction</span><span class="p">):</span>
        <span class="n">next_handler</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rax</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[+] Next handler executed: 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">next_handler</span><span class="p">))</span>
    <span class="k">pass</span>
</code></pre></div></div>

<p>If we include this code in the script, and we run it, we will obtain an output like the next one:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/14.png"><img src="/assets/images/hacklu-ollvm/14.png" /></a>
<figcaption>List of handlers run by the program.</figcaption>
</figure>

<p>Here we automatically extracted the list of handlers the program runs. Just including a few lines after processing the instruction.</p>

<h4 id="obtaining-the-intermediate-expressions">Obtaining the Intermediate expressions</h4>

<p>Each of the handlers will calculate a hash that can be used in the subsequent handlers as values to make the final expression harder to reverse. Additionally, they will provide an output that is significantly different from the input value. To determine the complexity of these handlers’ expressions, we can obtain their expressions using the Triton API. For this purpose, I have selected two handlers with addresses <code class="language-plaintext highlighter-rouge">0x0040fa60</code> and <code class="language-plaintext highlighter-rouge">0x0042C730</code>. For each of these handlers, we will identify the address where the resulting hash is stored:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/16.png"><img src="/assets/images/hacklu-ollvm/16.png" /></a>
</figure>

<figure>
<a href="/assets/images/hacklu-ollvm/18.png"><img src="/assets/images/hacklu-ollvm/18.png" /></a>
</figure>

<p>Since each handler uses <code class="language-plaintext highlighter-rouge">RAX</code> as the register, we will inspect each one of the addresses, retrieve the <code class="language-plaintext highlighter-rouge">AST</code> expression, and then <code class="language-plaintext highlighter-rouge">unroll</code> it with the following code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">post_execution</span><span class="p">(</span><span class="n">previous_pc</span><span class="p">,</span> <span class="n">instruction</span><span class="p">,</span> <span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Code to call after processing an instruction
    '''</span>
    <span class="p">...</span>
    <span class="c1"># analyze newer values pushed into the bytecode
</span>    <span class="k">if</span> <span class="n">previous_pc</span> <span class="ow">in</span> <span class="p">[</span><span class="mh">0x0040fdab</span><span class="p">,</span> <span class="mh">0x0042ccf1</span><span class="p">]:</span>
        <span class="n">rax</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rax</span><span class="p">)</span>
        <span class="n">mem_stored</span> <span class="o">=</span> <span class="n">rax</span><span class="o">*</span><span class="mi">8</span> <span class="o">+</span> <span class="mh">0x67b280</span>
        <span class="n">ast_mem</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicMemory</span><span class="p">(</span><span class="n">mem_stored</span><span class="p">).</span><span class="n">getAst</span><span class="p">()</span>
        <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
        <span class="k">print</span><span class="p">(</span><span class="n">ast</span><span class="p">.</span><span class="n">unroll</span><span class="p">(</span><span class="n">ast_mem</span><span class="p">))</span>
        <span class="nb">input</span><span class="p">(</span><span class="s">"ENTER"</span><span class="p">)</span>
    <span class="p">...</span>
    <span class="k">pass</span>
</code></pre></div></div>

<p>Running this, we will obtain each one of the expressions for each calculated hash:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[+] Next handler executed: 0x0040FA60
((_ extract 7 0) (bvadd (bvmul ((_ zero_extend 32) (bvand ((_ extract 31 0) (bvshl (bvadd (bvmul (bvsub SymVar_0 SymVar_0) SymVar_0) 
(bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) 
(_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64))
(bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64))))) (bvneg (bvsub (bvsub SymVar_0 
(_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64))))))
(bvand ((_ zero_extend 56) ((_ extract 7 0) (bvadd (bvmul (bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub 
(bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor 
(bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64))))) (bvneg (bvsub (bvsub SymVar_0 
(_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64))))))))
(_ bv63 64)))) (_ bv1 32))) (_ bv7413137316104562390 64)) (bvadd (bvxor (_ bv12906354758612225394 64) (bvadd (bvmul 
(bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub (bvsub SymVar_0 
(_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))))
(bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64))))))) (_ bv10072043083552405557 64))))
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[+] Next handler executed: 0x0042C730
((_ extract 7 0) (bvmul (bvshl (bvxor (_ bv14887247549634619895 64) (bvadd (bvmul ((_ zero_extend 32) (bvand ((_ extract 31 0) 
(bvshl (bvadd (bvmul (bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64))
(bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub 
(bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64))))) (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) 
(_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))))) (bvand ((_ zero_extend 56) ((_ extract 7 0) (bvadd (bvmul 
(bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor 
(bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub (bvsub SymVar_0 
(_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64))))) (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64)))))))) (_ bv63 64)))) (_ bv1 32))) (_ bv7413137316104562390 64)) (bvadd (bvxor (_ bv12906354758612225394 64)
(bvadd (bvmul (bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) 
(bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub 
(bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64))))) (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) 
(_ bv18446744073709551614 64)) (_ bv18446744073709551614 64))))))) (_ bv10072043083552405557 64)))) (_ bv32 64)) ((_ zero_extend 32) 
(bvand (bvnot (bvor (_ bv190 32) (bvnot (bvxor (bvor (bvsub (_ bv4294967289 32) (bvor (_ bv5 32) (bvsub (_ bv4294967294 32) 
(bvand (_ bv4 32) (bvor (bvadd (bvor (bvneg ((_ extract 31 0) (bvadd (bvmul ((_ zero_extend 32) (bvand ((_ extract 31 0) (bvshl 
(bvadd (bvmul (bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) 
(bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub 
(bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64))))) (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) 
(_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))))) (bvand ((_ zero_extend 56) ((_ extract 7 0) (bvadd (bvmul 
(bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor 
(bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub (bvsub SymVar_0 
(_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))))
(bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64)))))))) (_ bv63 64)))) (_ bv1 32))) (_ bv7413137316104562390 64)) (bvadd (bvxor (_ bv12906354758612225394 64)
(bvadd (bvmul (bvsub SymVar_0 SymVar_0) SymVar_0) (bvand (bvor (bvxor (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) 
(bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) (_ bv18446744073709551614 64)))) (_ bv2 64)) (bvneg (bvsub 
(bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) (_ bv18446744073709551614 64)) 
(_ bv18446744073709551614 64))))) (bvneg (bvsub (bvsub SymVar_0 (_ bv5610100774807237061 64)) (bvxor (bvxor (bvadd SymVar_0 SymVar_0) 
(_ bv18446744073709551614 64)) (_ bv18446744073709551614 64))))))) (_ bv10072043083552405557 64))))) (_ bv8557572 32)) (_ bv1 32)) 
(_ bv8525316 32)))))) (_ bv244 32)) (_ bv91 32))))) (_ bv91 32)))))
</code></pre></div></div>

<p>From the previous output, we can observe that we obtain a complex AST that would likely be difficult to solve manually.</p>

<p>However, we do not need to solve this complex AST, as it is unnecessary to solve the challenge. Instead, we only need the last expression retrieved from the <code class="language-plaintext highlighter-rouge">main</code> function.</p>

<h4 id="solving-the-challenge">Solving the Challenge</h4>

<p>In this challenge, we are provided with a given value as input and an output generated by the program. Based on information gathered from researching the challenge and examining Jonathan’s script, our task is to find eight input values that produce the following hashes as output: <code class="language-plaintext highlighter-rouge">0x875cd4f2e18f8fc4</code>, <code class="language-plaintext highlighter-rouge">0xbb093e17e5d3fa42</code>, <code class="language-plaintext highlighter-rouge">0xada5dd034aae16b4</code>, <code class="language-plaintext highlighter-rouge">0x97322728fea51225</code>, <code class="language-plaintext highlighter-rouge">0x4124799d72188d0d</code>, <code class="language-plaintext highlighter-rouge">0x2b3e3fbbb4d44981</code>, <code class="language-plaintext highlighter-rouge">0xdfcac668321e4daa</code>, and <code class="language-plaintext highlighter-rouge">0xeac2137a35c8923a</code>. The process will be as follows:</p>

<ol>
  <li>Symbolize the output from <code class="language-plaintext highlighter-rouge">strtoul</code> to work with a symbolic value.</li>
  <li>Execute the handlers until the program returns to the <code class="language-plaintext highlighter-rouge">main</code> function.</li>
  <li>Extract the expression from the parameter of the <code class="language-plaintext highlighter-rouge">printf</code> function.</li>
  <li>Transform the expression to <code class="language-plaintext highlighter-rouge">Z3</code> format.</li>
  <li>Inject each of the hashes as a constraint and solve the challenge.</li>
</ol>

<p>As mentioned before, we already saw the code for setting the output of <code class="language-plaintext highlighter-rouge">strtoul</code> as symbolic:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">strtoul</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Hook for strtoul
    '''</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'[+] strtoul hooked'</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">SYMBOLIC</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="s">"0xdeadbeef"</span><span class="p">,</span> <span class="mi">16</span><span class="p">))</span>
</code></pre></div></div>

<p>With this, the concrete value <code class="language-plaintext highlighter-rouge">0xdeadbeef</code> will be set in <code class="language-plaintext highlighter-rouge">RAX</code> and the operations with the value will be tracked. Then we just need to keep emulating for running the different handlers. Then we will stop the emulation after running the next instruction:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/19.png"><img src="/assets/images/hacklu-ollvm/19.png" /></a>
<figcaption>End of main function, execution of printf.</figcaption>
</figure>

<p>At address <code class="language-plaintext highlighter-rouge">0x004008d3</code>, the program retrieves the resulting hash from one memory location. This is the instruction where we will stop in the <code class="language-plaintext highlighter-rouge">post_execution</code> function. The value is moved to the <code class="language-plaintext highlighter-rouge">RSI</code> register, which Ghidra renames as <code class="language-plaintext highlighter-rouge">argv</code>. We will then retrieve the full expression from <code class="language-plaintext highlighter-rouge">RSI</code>, and for each of the previous hash values, we will create rounds with different constraints.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">hashes_to_check</span> <span class="o">=</span> <span class="p">[</span>
    <span class="mh">0x875cd4f2e18f8fc4</span><span class="p">,</span>
    <span class="mh">0xbb093e17e5d3fa42</span><span class="p">,</span>
    <span class="mh">0xada5dd034aae16b4</span><span class="p">,</span>
    <span class="mh">0x97322728fea51225</span><span class="p">,</span>
    <span class="mh">0x4124799d72188d0d</span><span class="p">,</span>
    <span class="mh">0x2b3e3fbbb4d44981</span><span class="p">,</span>
    <span class="mh">0xdfcac668321e4daa</span><span class="p">,</span>
    <span class="mh">0xeac2137a35c8923a</span>
<span class="p">]</span>


<span class="k">def</span> <span class="nf">post_execution</span><span class="p">(</span><span class="n">previous_pc</span><span class="p">,</span> <span class="n">instruction</span><span class="p">,</span> <span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Code to call after processing an instruction
    '''</span>
    <span class="p">...</span>
    <span class="k">if</span> <span class="n">previous_pc</span> <span class="o">==</span> <span class="mh">0x004008d3</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">instruction</span><span class="p">))</span>
        <span class="n">flag</span><span class="o">=</span><span class="s">""</span>
        <span class="n">rsi</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getRegisterAst</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">)</span>
        <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>

        <span class="k">for</span> <span class="n">hash_to_check</span> <span class="ow">in</span> <span class="n">hashes_to_check</span><span class="p">:</span>
            
            <span class="n">model</span> <span class="o">=</span> <span class="n">myExternalSolver</span><span class="p">(</span>
                <span class="n">ctx</span><span class="p">,</span> <span class="n">rsi</span> <span class="o">==</span> <span class="n">hash_to_check</span><span class="p">,</span> <span class="n">previous_pc</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">model</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
                <span class="k">print</span><span class="p">(</span><span class="s">"Value %d in decimal: 0x%08X for hash %08x"</span> <span class="o">%</span>
                      <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">hash_to_check</span><span class="p">))</span>
                <span class="n">flag</span> <span class="o">+=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">v</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="s">'0x'</span><span class="p">,</span><span class="s">''</span><span class="p">)).</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Flag </span><span class="si">{</span><span class="n">flag</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="k">pass</span>
</code></pre></div></div>

<p>I am using here the same function that we saw at the end of the previous post, <code class="language-plaintext highlighter-rouge">myExternalSolver</code>. These functions are used for generating the Z3 expressions and solving them to obtain the flag:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">getVarSyntax</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Retrieve all the declared symbolic variables
    and generatae them as a string like the next:

    (declare-fun SymVar_0 () (_ BitVec 8))

    :param ctx: triton context for using utilities
    '''</span>
    <span class="n">s</span> <span class="o">=</span> <span class="nb">str</span><span class="p">()</span>
    <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicVariables</span><span class="p">().</span><span class="n">items</span><span class="p">()):</span>
        <span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">ast</span><span class="p">.</span><span class="n">declare</span><span class="p">(</span><span class="n">ast</span><span class="p">.</span><span class="n">variable</span><span class="p">(</span><span class="n">v</span><span class="p">)))</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
    <span class="k">return</span> <span class="n">s</span>


<span class="k">def</span> <span class="nf">getSSA</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">expr</span><span class="p">):</span>
    <span class="s">'''
    Get an SSA version of the expression given as parameter
    this will generate all the expressions in an IR form
    with SSA form.

    :param ctx: triton context for using utilities
    :param expr: expression to retrieve its SSA form
    '''</span>
    <span class="n">s</span> <span class="o">=</span> <span class="nb">str</span><span class="p">()</span>
    <span class="c1"># current AST of the program
</span>    <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
    <span class="c1"># generate an IR in SSA from the expression
</span>    <span class="n">ssa</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">sliceExpressions</span><span class="p">(</span><span class="n">expr</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">ssa</span><span class="p">.</span><span class="n">items</span><span class="p">())[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
        <span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
    <span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">ast</span><span class="p">.</span><span class="n">assert_</span><span class="p">(</span><span class="n">expr</span><span class="p">.</span><span class="n">getAst</span><span class="p">()))</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
    <span class="k">return</span> <span class="n">s</span>


<span class="k">def</span> <span class="nf">myExternalSolver</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">addr</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
    <span class="s">"""
    The particularity of this sample is that we use an external solver to solve
    queries instead of using the internal Triton's solver (even if in both cases
    it uses z3). The point here is to show that Triton can provide generic smt2
    outputs and theses outputs can be send to external solvers and get back model
    which then are sent to Triton.
    """</span>
    <span class="kn">import</span> <span class="nn">z3</span>
    <span class="n">expr</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">newSymbolicExpression</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="s">"Custom for Solver"</span><span class="p">)</span>
    <span class="n">varSyntax</span> <span class="o">=</span> <span class="n">getVarSyntax</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
    <span class="n">ssa</span> <span class="o">=</span> <span class="n">getSSA</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">expr</span><span class="p">)</span>

    <span class="n">smtFormat</span> <span class="o">=</span> <span class="s">'(set-logic QF_BV) %s %s (check-sat) (get-model)'</span> <span class="o">%</span> <span class="p">(</span>
        <span class="n">varSyntax</span><span class="p">,</span> <span class="n">ssa</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">debug</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">smtFormat</span><span class="p">)</span>

    <span class="n">c</span> <span class="o">=</span> <span class="n">z3</span><span class="p">.</span><span class="n">Context</span><span class="p">()</span>
    <span class="n">s</span> <span class="o">=</span> <span class="n">z3</span><span class="p">.</span><span class="n">Solver</span><span class="p">(</span><span class="n">ctx</span><span class="o">=</span><span class="n">c</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">z3</span><span class="p">.</span><span class="n">parse_smt2_string</span><span class="p">(</span><span class="n">smtFormat</span><span class="p">,</span> <span class="n">ctx</span><span class="o">=</span><span class="n">c</span><span class="p">))</span>
    <span class="k">if</span> <span class="n">addr</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">'[+] Solving condition at %#x'</span> <span class="o">%</span> <span class="p">(</span><span class="n">addr</span><span class="p">))</span>
    <span class="k">if</span> <span class="n">s</span><span class="p">.</span><span class="n">check</span><span class="p">()</span> <span class="o">==</span> <span class="n">z3</span><span class="p">.</span><span class="n">sat</span><span class="p">:</span>
        <span class="n">ret</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">model</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">model</span><span class="p">:</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="s">"ref"</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
                <span class="n">ret</span><span class="p">.</span><span class="n">update</span><span class="p">(</span>
                    <span class="p">{</span><span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">'_'</span><span class="p">)[</span><span class="mi">1</span><span class="p">],</span> <span class="mi">10</span><span class="p">):</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">model</span><span class="p">[</span><span class="n">x</span><span class="p">]),</span> <span class="mi">10</span><span class="p">)})</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">continue</span>
        <span class="k">return</span> <span class="n">ret</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">'[-] unsat :('</span><span class="p">)</span>
        <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span>
</code></pre></div></div>

<p>Now we have all the different pieces for obtaining the output flag:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/20.png"><img src="/assets/images/hacklu-ollvm/20.png" /></a>
</figure>

<figure>
<a href="/assets/images/hacklu-ollvm/21.png"><img src="/assets/images/hacklu-ollvm/21.png" /></a>
</figure>

<figure>
<a href="/assets/images/hacklu-ollvm/22.png"><img src="/assets/images/hacklu-ollvm/22.png" /></a>
<figcaption>Solution of the challenge solved as numbers of 8 bytes and joined in a string.</figcaption>
</figure>

<p>We have solved the expression for each one of the hashes, and we finally obtained the Flag: <code class="language-plaintext highlighter-rouge">mirror_mirror_on_the_wall_whos_the_ugliest_handler_of_them_all?!</code>, and with this we would have finished the challenge!</p>

<h4 id="llvm-ir-and-cleaning-the-expression">LLVM IR and Cleaning the Expression</h4>

<p>Before concluding this post, I will show a couple of interesting things. Triton uses an Abstract Syntax Tree (AST) internally to keep track of the symbolic expression, but it allows lifting this AST to <code class="language-plaintext highlighter-rouge">LLVM IR</code>. LLVM is a compiler framework that works with a comprehensive Intermediate Representation (IR), enabling the representation of high-level code and allowing the application of various compiler optimizations. Utilizing <code class="language-plaintext highlighter-rouge">LLVM IR</code> can be beneficial for analyzing binary code, as we can directly apply these optimizations to the IR instead of the assembly code. Another intriguing feature of Triton is the ability to apply optimizations to the generated IR. We will include the following code in the solution for the challenge:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">post_execution</span><span class="p">(</span><span class="n">previous_pc</span><span class="p">,</span> <span class="n">instruction</span><span class="p">,</span> <span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    Code to call after processing an instruction
    '''</span>
    <span class="k">if</span> <span class="n">previous_pc</span> <span class="o">==</span> <span class="mh">0x004008d3</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">instruction</span><span class="p">))</span>
        <span class="n">flag</span><span class="o">=</span><span class="s">""</span>
        <span class="n">rsi</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getRegisterAst</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">)</span>
        <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
        <span class="n">M</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">liftToLLVM</span><span class="p">(</span><span class="n">rsi</span><span class="p">,</span> <span class="n">fname</span><span class="o">=</span><span class="s">"expression_ollvm"</span><span class="p">,</span> <span class="n">optimize</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"Not simplified RSI:"</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="n">M</span><span class="p">)</span>
        <span class="n">M</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">liftToLLVM</span><span class="p">(</span><span class="n">rsi</span><span class="p">,</span> <span class="n">fname</span><span class="o">=</span><span class="s">"expression_ollvm"</span><span class="p">,</span> <span class="n">optimize</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"Simplified RSI Through LLVM:"</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="n">M</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">hash_to_check</span> <span class="ow">in</span> <span class="n">hashes_to_check</span><span class="p">:</span>
            
            <span class="n">model</span> <span class="o">=</span> <span class="n">myExternalSolver</span><span class="p">(</span>
                <span class="n">ctx</span><span class="p">,</span> <span class="n">rsi</span> <span class="o">==</span> <span class="n">hash_to_check</span><span class="p">,</span> <span class="n">previous_pc</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">model</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
                <span class="k">print</span><span class="p">(</span><span class="s">"Value %d in decimal: 0x%08X for hash %08x"</span> <span class="o">%</span>
                      <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">hash_to_check</span><span class="p">))</span>
                <span class="n">flag</span> <span class="o">+=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">v</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="s">'0x'</span><span class="p">,</span><span class="s">''</span><span class="p">)).</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Flag </span><span class="si">{</span><span class="n">flag</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="k">pass</span>
</code></pre></div></div>

<p>The Not simplified expression is the next one:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; ModuleID = 'tritonModule'
source_filename = "tritonModule"

define i64 @expression_ollvm(i64 %SymVar_0) {
entry:
  %0 = add i64 %SymVar_0, %SymVar_0
  %1 = xor i64 %0, -2
  %2 = xor i64 %1, -2
  %3 = sub i64 %SymVar_0, 5610100774807237061
  %4 = sub i64 %3, %2
  %5 = sub i64 0, %4
  %6 = xor i64 %5, 2
  %7 = or i64 %6, %5
  %8 = and i64 %7, %5
  %9 = sub i64 %SymVar_0, %SymVar_0
  %10 = mul i64 %9, %SymVar_0
  %11 = add i64 %10, %8
  %12 = xor i64 -5540389315097326222, %11
  %13 = add i64 %12, -8374700990157146059
  %14 = trunc i64 %11 to i8
  %15 = zext i8 %14 to i64
  %16 = and i64 %15, 63
  %17 = shl i64 %11, %16
  %18 = trunc i64 %17 to i32
  %19 = and i32 %18, 1
  %20 = zext i32 %19 to i64
  %21 = mul i64 %20, 7413137316104562390
  %22 = add i64 %21, %13
  %23 = xor i64 -3559496524074931721, %22
  %24 = shl i64 %23, 32
  %25 = lshr i64 %23, 32
  %26 = xor i64 %22, -1
  %27 = and i64 %26, -3559496524074931721
  %28 = and i64 3559496524074931720, %22
  %29 = trunc i64 %28 to i32
  %30 = and i32 %29, 2
  %31 = zext i32 %30 to i64
  %32 = sub i64 0, %31
  %33 = add i64 -1, %31
  %34 = and i64 %28, %32
  %35 = or i64 %34, %33
  %36 = xor i64 %35, %28
  %37 = and i64 %36, %32
  %38 = or i64 %37, %28
  %39 = sub i64 %38, %31
  %40 = or i64 %39, %28
  %41 = add i64 %40, %27
  %42 = shl i64 %41, 32
  %43 = xor i64 %42, -1
  %44 = or i64 %43, %24
  %45 = xor i64 %44, %25
  %46 = xor i64 %45, -1
  %47 = trunc i64 %23 to i32
  %48 = and i32 %47, 63
  %49 = trunc i32 %48 to i8
  %50 = zext i8 %49 to i64
  %51 = and i64 %50, 63
  %52 = shl i64 32, %51
  %53 = trunc i64 %52 to i32
  %54 = and i32 %53, %48
  %55 = trunc i32 %54 to i8
  %56 = zext i8 %55 to i64
  %57 = and i64 %56, 63
  %58 = shl i64 32, %57
  %59 = trunc i64 %58 to i8
  %60 = zext i8 %59 to i64
  %61 = and i64 %60, 63
  %62 = shl i64 %23, %61
  %63 = or i64 %62, %46
  %64 = xor i64 %24, -1
  %65 = and i64 %64, %63
  %66 = xor i64 %65, %24
  %67 = trunc i64 %66 to i32
  %68 = zext i32 %67 to i64
  %69 = or i64 %68, -2
  %70 = and i64 %66, %69
  %71 = mul i64 -6464709178843836683, %70
  %72 = add i64 %71, 1779491018601202359
  %73 = and i64 %72, %72
  %74 = icmp eq i64 %73, 0
  %75 = select i1 %74, i1 true, i1 false
  %76 = icmp eq i1 %75, true
  %77 = select i1 %76, i64 56, i64 0
  %78 = add i64 %77, 3179662501
  %79 = xor i64 -3559496524074931721, %22
  %80 = lshr i64 %79, 32
  %81 = trunc i64 %80 to i32
  %82 = trunc i64 %80 to i32
  %83 = mul i32 %82, %81
  %84 = trunc i32 %83 to i8
  %85 = and i8 %84, 2
  %86 = zext i8 %85 to i64
  %87 = and i64 %86, 63
  %88 = trunc i64 %22 to i32
  %89 = sub i32 0, %88
  %90 = or i32 %89, 8557572
  %91 = add i32 %90, 1
  %92 = or i32 %91, 8525316
  %93 = and i32 4, %92
  %94 = sub i32 -2, %93
  %95 = or i32 5, %94
  %96 = sub i32 -7, %95
  %97 = or i32 %96, 244
  %98 = xor i32 %97, 91
  %99 = xor i32 %98, -1
  %100 = or i32 190, %99
  %101 = xor i32 %100, -1
  %102 = and i32 %101, 91
  %103 = zext i32 %102 to i64
  %104 = xor i64 -3559496524074931721, %22
  %105 = shl i64 %104, 32
  %106 = mul i64 %105, %103
  %107 = mul i64 %106, 2
  %108 = xor i64 %106, -1
  %109 = add i64 %108, %107
  %110 = add i64 %109, 1
  %111 = or i64 %110, %106
  %112 = add i64 %111, -1
  %113 = and i64 %112, %80
  %114 = xor i64 %113, %106
  %115 = or i64 %114, %80
  %116 = add i64 -1, %106
  %117 = and i64 %116, %80
  %118 = xor i64 %117, %106
  %119 = or i64 %118, %80
  %120 = add i64 %119, 1
  %121 = add i64 %118, %106
  %122 = trunc i64 %80 to i32
  %123 = and i32 %122, 2
  %124 = zext i32 %123 to i64
  %125 = xor i64 %124, 2
  %126 = and i64 %125, %80
  %127 = or i64 %126, %106
  %128 = add i64 %127, -1
  %129 = and i64 %128, %80
  %130 = xor i64 %129, %106
  %131 = sub i64 %130, %108
  %132 = xor i64 %118, -1
  %133 = add i64 %132, %108
  %134 = xor i64 %133, %106
  %135 = xor i64 %134, %131
  %136 = add i64 %135, %121
  %137 = add i64 %136, 1
  %138 = or i64 %137, %80
  %139 = and i64 %138, %120
  %140 = or i64 %139, %115
  %141 = shl i64 %140, %87
  %142 = mul i64 %141, -6464709178843836683
  %143 = mul i64 2, %142
  %144 = sub i64 0, %142
  %145 = add i64 %144, %143
  %146 = trunc i64 %145 to i8
  %147 = zext i8 %146 to i64
  %148 = and i64 %147, 63
  %149 = shl i64 %145, %148
  %150 = trunc i64 %149 to i32
  %151 = and i32 %150, 1
  %152 = zext i32 %151 to i64
  %153 = or i64 %152, -52618
  %154 = add i64 %153, 52617
  %155 = ashr i64 %154, 63
  %156 = add i64 1779491018601202359, %145
  %157 = lshr i64 %156, 8
  %158 = mul i64 %157, %155
  %159 = sub i64 0, %158
  %160 = shl i64 %159, 54
  %161 = trunc i64 %160 to i32
  %162 = and i32 %161, 689829814
  %163 = and i32 %162, 1
  %164 = zext i32 %163 to i64
  %165 = xor i64 %164, 689829814
  %166 = xor i64 %165, -1
  %167 = and i64 689829813, %166
  %168 = xor i64 %167, -1
  %169 = or i64 %168, 2
  %170 = add i64 %169, -2
  %171 = xor i64 %170, -1
  %172 = lshr i64 %171, 63
  %173 = mul i64 %172, %78
  %174 = trunc i64 %72 to i32
  %175 = add i64 -1, %72
  %176 = trunc i64 %175 to i32
  %177 = and i32 %176, %174
  %178 = and i32 %177, 1
  %179 = xor i32 %178, 63
  %180 = and i32 56, %179
  %181 = trunc i32 %180 to i8
  %182 = zext i8 %181 to i64
  %183 = and i64 %182, 63
  %184 = shl i64 %72, %183
  %185 = or i64 %184, %159
  %186 = mul i64 %185, -1
  %187 = sub i64 0, %186
  %188 = add i64 %187, %173
  %189 = xor i64 %188, 3633819531175615211
  %190 = add i64 %189, 3014537922511877372
  %191 = mul i64 -1, %190
  %192 = sub i64 0, %191
  %193 = or i64 %191, %192
  %194 = xor i64 %192, %191
  %195 = and i64 %194, %193
  %196 = xor i64 %188, -3633819531175615212
  %197 = add i64 -1, %188
  %198 = and i64 %197, %188
  %199 = sub i64 0, %188
  %200 = and i64 %199, %188
  %201 = xor i64 -3633819531175615212, %200
  %202 = xor i64 %201, %198
  %203 = or i64 %202, %189
  %204 = xor i64 %203, %196
  %205 = add i64 %204, 3014537922511877372
  %206 = add i64 %205, %205
  %207 = sub i64 %206, %190
  %208 = mul i64 %207, -1
  %209 = xor i64 %208, %195
  %210 = trunc i64 %209 to i8
  %211 = zext i8 %210 to i64
  %212 = and i64 %211, 63
  %213 = shl i64 %209, %212
  %214 = trunc i64 %213 to i32
  %215 = and i32 %214, 1
  %216 = zext i32 %215 to i64
  %217 = xor i64 -3, %216
  %218 = add i64 -2, %217
  %219 = and i64 %218, %217
  %220 = xor i64 -3, %216
  %221 = or i64 %220, %219
  %222 = add i64 %221, 2
  %223 = xor i64 -3, %216
  %224 = or i64 %223, %219
  %225 = add i64 %224, 2
  %226 = and i64 -71777214294589693, %225
  %227 = or i64 %226, %222
  %228 = shl i64 %209, 8
  %229 = and i64 %228, -71777214294589696
  %230 = mul i64 %229, %227
  %231 = sub i64 0, %230
  %232 = add i64 %231, %231
  %233 = shl i64 %232, 20
  %234 = trunc i64 %233 to i32
  %235 = xor i32 %234, -1
  %236 = or i32 %235, -2
  %237 = and i32 %236, 27293611
  %238 = zext i32 %237 to i64
  %239 = add i64 %238, -1
  %240 = ashr i64 %239, 63
  %241 = and i64 %240, -4611686018427387904
  %242 = xor i64 %241, -1
  %243 = add i64 %242, %240
  %244 = xor i64 %243, -1
  %245 = add i64 %244, %240
  %246 = lshr i64 %209, 8
  %247 = trunc i64 %246 to i32
  %248 = and i32 %247, 63
  %249 = trunc i32 %248 to i8
  %250 = zext i8 %249 to i64
  %251 = and i64 %250, 63
  %252 = shl i64 1, %251
  %253 = trunc i64 %252 to i32
  %254 = and i32 %248, %253
  %255 = trunc i32 %254 to i8
  %256 = zext i8 %255 to i64
  %257 = and i64 %256, 63
  %258 = shl i64 %246, %257
  %259 = and i64 %258, 71777214294589695
  %260 = or i64 %259, 2
  %261 = xor i64 %260, -1
  %262 = or i64 %259, -3
  %263 = add i64 %259, %259
  %264 = xor i64 %263, -1
  %265 = add i64 %264, %259
  %266 = xor i64 %265, %262
  %267 = and i64 %266, %259
  %268 = xor i64 %267, %260
  %269 = or i64 %268, %261
  %270 = sub i64 %260, %259
  %271 = xor i64 %270, %259
  %272 = and i64 %260, %259
  %273 = and i64 %272, %271
  %274 = add i64 %273, %269
  %275 = trunc i64 %259 to i32
  %276 = trunc i64 %259 to i32
  %277 = mul i32 %276, %275
  %278 = and i32 %277, 2
  %279 = xor i64 %259, -1
  %280 = trunc i64 %279 to i32
  %281 = or i32 %280, %278
  %282 = zext i32 %281 to i64
  %283 = xor i64 %231, -1
  %284 = or i64 %283, %259
  %285 = add i64 %284, %282
  %286 = trunc i64 %285 to i32
  %287 = add i32 %286, 1
  %288 = trunc i64 %259 to i32
  %289 = trunc i64 %284 to i32
  %290 = trunc i64 %259 to i32
  %291 = trunc i64 %231 to i32
  %292 = xor i32 %291, -1
  %293 = or i32 %292, %290
  %294 = and i32 %293, 2
  %295 = or i32 %294, %289
  %296 = sub i32 %295, %288
  %297 = mul i32 %296, %287
  %298 = and i32 %297, 2
  %299 = zext i32 %298 to i64
  %300 = add i64 %284, %279
  %301 = xor i64 %300, -1
  %302 = or i64 %301, %299
  %303 = add i64 %302, %274
  %304 = or i64 %303, %231
  %305 = sub i64 0, %245
  %306 = or i64 %304, %305
  %307 = xor i64 %306, -1
  %308 = or i64 %307, %304
  %309 = mul i64 -1, %304
  %310 = sub i64 0, %309
  %311 = or i64 %310, %305
  %312 = and i64 %304, %311
  %313 = and i64 %312, %308
  %314 = add i64 %313, %245
  %315 = xor i64 -5064113576967571667, %314
  %316 = mul i64 %315, 5906144455206004469
  %317 = sub i64 0, %316
  %318 = add i64 %316, -1
  %319 = or i64 %318, 1
  %320 = sub i64 0, %319
  %321 = and i64 %320, %317
  ret i64 %321
}
</code></pre></div></div>

<p>And the simplified expression is the next one:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; ModuleID = 'tritonModule'
source_filename = "tritonModule"

; Function Attrs: norecurse nounwind readnone willreturn
define i64 @expression_ollvm(i64 %SymVar_0) local_unnamed_addr #0 {
entry:
  %.neg.neg = shl i64 %SymVar_0, 1
  %.neg1 = sub i64 5610100774807237061, %SymVar_0
  %.neg2 = add i64 %.neg.neg, %.neg1
  %0 = xor i64 %.neg2, -5540389315097326222
  %1 = add i64 %0, -8374700990157146059
  %2 = and i64 %.neg2, 63
  %3 = shl i64 %.neg2, %2
  %4 = and i64 %3, 1
  %5 = mul nuw nsw i64 %4, 7413137316104562390
  %6 = add i64 %1, %5
  %7 = xor i64 %6, -3559496524074931721
  %8 = shl i64 %7, 32
  %9 = shl i64 %6, 32
  %10 = xor i64 %9, -3983057798777798657
  %11 = or i64 %10, %8
  %12 = lshr i64 %6, 32
  %13 = xor i64 %12, %11
  %14 = xor i64 %13, -3466207430
  %15 = and i64 %7, 63
  %16 = shl i64 32, %15
  %17 = and i64 %15, %16
  %18 = shl i64 32, %17
  %19 = and i64 %18, 63
  %20 = shl i64 %7, %19
  %21 = or i64 %14, %8
  %22 = or i64 %21, %20
  %23 = xor i64 %12, 3466207429
  %24 = trunc i64 %23 to i8
  %25 = mul i8 %24, %24
  %26 = and i8 %25, 2
  %27 = zext i8 %26 to i64
  %28 = xor i64 %9, 3983057798777798656
  %29 = or i64 %23, %28
  %30 = add i64 %29, 1
  %31 = and i64 %12, 2
  %32 = xor i64 %31, 2
  %33 = and i64 %32, %12
  %34 = add nuw nsw i64 %33, 4294967295
  %35 = and i64 %34, %23
  %36 = sub i64 %28, %10
  %37 = add i64 %36, %35
  %38 = xor i64 %29, -1
  %39 = add i64 %10, %38
  %40 = xor i64 %39, %28
  %41 = xor i64 %40, %37
  %42 = add i64 %30, %28
  %43 = add i64 %42, %41
  %44 = or i64 %43, %23
  %45 = and i64 %44, %30
  %46 = or i64 %45, %29
  %47 = shl i64 %46, %27
  %48 = mul i64 %47, -6464709178843836683
  %49 = and i64 %48, 63
  %50 = shl i64 %48, %49
  %51 = and i64 %50, 1
  %52 = add nuw nsw i64 %51, 72057594037927935
  %53 = add i64 %48, 1779491018601202359
  %54 = lshr i64 %53, 8
  %.neg3 = and i64 %52, %54
  %.neg.neg6 = mul i64 %22, -792633534417207296
  %.neg4.neg = add i64 %.neg.neg6, -5260204364768739328
  %.neg5.neg = or i64 %.neg3, %.neg4.neg
  %55 = xor i64 %.neg5.neg, 3633819531175615211
  %.neg = add i64 %55, 3014537922511877372
  %56 = sub i64 -3014537922511877372, %55
  %57 = xor i64 %.neg, %56
  %58 = xor i64 %.neg5.neg, 5589552505679160596
  %59 = or i64 %58, %55
  %60 = xor i64 %59, %.neg5.neg
  %61 = shl i64 %60, 1
  %62 = xor i64 %61, 7267639062351230423
  %63 = add i64 %55, -3014537922511877371
  %.neg7 = add i64 %63, %62
  %64 = xor i64 %57, %.neg7
  %65 = and i64 %64, 63
  %66 = shl i64 %64, %65
  %67 = and i64 %66, 1
  %.neg10 = add nuw nsw i64 %67, 1
  %68 = shl i64 %64, 8
  %69 = and i64 %68, -71777214294589696
  %.neg11 = mul i64 %.neg10, %69
  %70 = lshr i64 %64, 8
  %71 = and i64 %70, 63
  %72 = shl nuw i64 1, %71
  %73 = and i64 %71, %72
  %74 = shl i64 %70, %73
  %75 = and i64 %74, 71777214294589695
  %76 = or i64 %75, 2
  %77 = xor i64 %76, -1
  %78 = or i64 %74, 71777214294589693
  %79 = shl nuw nsw i64 %75, 1
  %80 = xor i64 %79, -1
  %81 = add nsw i64 %75, %80
  %82 = xor i64 %81, %78
  %83 = and i64 %82, %74
  %84 = xor i64 %83, %76
  %85 = or i64 %84, %77
  %86 = add nsw i64 %75, %77
  %87 = and i64 %86, %75
  %88 = add nsw i64 %85, %87
  %89 = trunc i64 %75 to i32
  %90 = mul i32 %89, %89
  %91 = and i32 %90, 2
  %92 = xor i32 %89, -1
  %93 = or i32 %91, %92
  %94 = xor i64 %.neg11, -1
  %95 = or i64 %75, %94
  %96 = trunc i64 %95 to i32
  %97 = add i32 %96, 1
  %98 = add i32 %97, %93
  %99 = sub i32 %96, %89
  %100 = mul i32 %98, %99
  %101 = and i32 %100, 2
  %102 = zext i32 %101 to i64
  %103 = sub i64 %75, %95
  %104 = or i64 %103, %102
  %105 = add i64 %88, %104
  %106 = or i64 %105, %.neg11
  %107 = xor i64 %106, -5064113576967571667
  %108 = mul i64 %107, 5906144455206004469
  %109 = sub i64 0, %108
  %110 = add i64 %108, -1
  %111 = or i64 %110, 1
  %112 = sub nsw i64 0, %111
  %113 = and i64 %112, %109
  ret i64 %113
}
</code></pre></div></div>

<p>In this case, the LLVM optimizer has been able to reduce the number of variables from 321 to 113. Once again, the final expression contains various arithmetic and logical instructions, as it also employs MBA obfuscation. To further clean the output, we will save the first <code class="language-plaintext highlighter-rouge">LLVM IR</code> into a file, and then use <a href="https://github.com/pgarba/SiMBA-">SiMBA-</a>, which is a C++ MBA Solver. There is a previous version in Python, <a href="https://github.com/DenuvoSoftwareSolutions/SiMBA">SiMBA</a>, which claims to be an <em>Efficient Deobfuscation of Linear Mixed Boolean-Arithmetic Expressions</em>, as stated on their GitHub repository. More information can be found in their <a href="https://github.com/DenuvoSoftwareSolutions/SiMBA/blob/main/paper/paper.pdf">paper</a>. In this case, it will be a simple test to obtain a simpler view of the expression:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>./SiMBA++ <span class="nt">-fastcheck</span> <span class="nt">-bitcount</span><span class="o">=</span>64 <span class="nt">-optimize</span><span class="o">=</span><span class="nb">true</span> <span class="nt">-detect-simplify</span> <span class="nt">-ir</span> /home/symbolic/Desktop/ollvm-challenge/LLVM-Files/expression_ollvm_opt.ll <span class="nt">-out</span> /home/symbolic/Desktop/ollvm-challenge/LLVM-Files/expression_ollvm_opt.simplify.ll
<span class="go">   _____ __  ______  ___    __    __ 
  / __(_)  |/  / _ )/ _ |__/ /___/ /_
 _\ \/ / /|_/ / _  / __ /_  __/_  __/
/___/_/_/  /_/____/_/ |_|/_/   /_/1.0
°°SiMBA ported to C/C++/LLVM ~pgarba~

[+] Loading LLVM Module: '/home/symbolic/Desktop/ollvm-challenge/LLVM-Files/expression_ollvm_opt.ll'
[+] Running LLVM optimizer (Some MBAs might already be simplified by that!) ...		 Done! (23 ms)
[+] Running LLVM optimizer ...		 Done! (6 ms)
[+] Wrote LLVM Module to: '/home/symbolic/Desktop/ollvm-challenge/LLVM-Files/expression_ollvm_opt.simplify.ll'
[+] MBAs found and replaced: '9' time: 166ms
</span></code></pre></div></div>

<p>The C++ version of SiMBA allows to provide the engine with an <code class="language-plaintext highlighter-rouge">LLVM IR</code> file as input, and then another one will be generated with the simplified expression, the output is the next one:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
define i64 @mba(i64 %SymVar_0) local_unnamed_addr #0 {
entry:
  %0 = add i64 %SymVar_0, 5610100774807237061
  %1 = xor i64 %0, -5540389315097326222
  %2 = add i64 %1, -8374700990157146059
  %3 = shl i64 %2, 32
  %4 = lshr i64 %2, 32
  %5 = or i64 %4, %3
  %6 = xor i64 %5, 3983057802244006085
  %7 = xor i64 %4, 3466207429
  %8 = xor i64 %3, 3983057798777798656
  %9 = or i64 %7, %8
  %10 = add i64 %9, 1
  %11 = xor i64 %3, -3983057798777798657
  %12 = add i64 %11, %8
  %13 = add i64 %12, %10
  %14 = or i64 %13, %7
  %15 = and i64 %14, %10
  %16 = or i64 %8, %15
  %17 = or i64 %16, %7
  %18 = mul i64 %17, -6464709178843836683
  %19 = add i64 %18, 1779491018601202359
  %20 = lshr i64 %19, 8
  %.neg4.neg = mul i64 %6, -792633534417207296
  %.neg5.neg = add i64 %.neg4.neg, -5260204364768739328
  %.neg6.neg = or i64 %20, %.neg5.neg
  %21 = xor i64 %.neg6.neg, 3633819531175615211
  %.neg7 = add i64 %21, 3014537922511877372
  %22 = sub i64 -3014537922511877372, %21
  %23 = xor i64 %.neg7, %22
  %24 = xor i64 %.neg6.neg, 5589552505679160596
  %25 = or i64 %24, %21
  %26 = xor i64 %25, %.neg6.neg
  %27 = shl i64 %26, 1
  %.neg9.neg = xor i64 %27, 7267639062351230423
  %.neg11 = add i64 %21, -3014537922511877371
  %28 = add i64 %.neg11, %.neg9.neg
  %29 = xor i64 %23, %28
  %30 = and i64 %29, 63
  %31 = shl i64 %29, %30
  %32 = and i64 %31, 1
  %.neg12 = add nuw nsw i64 %32, 1
  %33 = shl i64 %29, 8
  %34 = and i64 %33, -71777214294589696
  %.neg13 = mul i64 %.neg12, %34
  %35 = lshr i64 %29, 8
  %36 = and i64 %35, 63
  %37 = shl nuw i64 1, %36
  %38 = and i64 %37, %36
  %39 = shl i64 %35, %38
  %40 = and i64 %39, 71777214294589695
  %41 = or i64 %40, 2
  %42 = or i64 %39, 71777214294589693
  %43 = shl nuw nsw i64 %40, 1
  %44 = xor i64 %43, -1
  %45 = add nsw i64 %40, %44
  %46 = xor i64 %45, %42
  %47 = and i64 %39, %46
  %48 = and i64 %47, %41
  %49 = xor i64 %48, -1
  %50 = xor i64 %41, -1
  %51 = add nsw i64 %40, %50
  %52 = and i64 %51, %40
  %53 = xor i64 %.neg13, -1
  %54 = or i64 %40, %53
  %55 = sub i64 %40, %54
  %56 = add i64 %55, %52
  %57 = add i64 %56, %49
  %58 = or i64 %57, %.neg13
  %59 = xor i64 %58, -5064113576967571667
  %60 = mul i64 %59, 5906144455206004469
  %61 = sub i64 0, %60
  %62 = add i64 %60, -1
  %63 = or i64 %62, 1
  %64 = sub nsw i64 0, %63
  %65 = and i64 %64, %61
  ret i64 %65
}
</code></pre></div></div>

<p>In this case, SiMBA was able to reduce the output from the lifted expression. All these files can be compiled into a binary, we can do it in a very simple way. First of all we will have a very simple C code that we will compile to <code class="language-plaintext highlighter-rouge">LLVM IR</code>.</p>

<pre><code class="language-C">/***
*   A simple file to be compiled to LLVM IR
*   and then copy the different expressions
*   into it for compiling a final file.
*/
#include &lt;stdio.h&gt;

long func(long symbol)
{
    return symbol + 5 + 2 * 4;
}

int main(int argc, char **argv)
{
    printf("This is just a test: %ld\n", func(argc));
    return argc;
}
</code></pre>

<p>Now we have to compile it just until generating the <code class="language-plaintext highlighter-rouge">LLVM IR</code>, for doing that we will need to use Clang, since is the front-end that LLVM offers for compilation of C code:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span>clang-16 <span class="nt">-S</span> <span class="nt">-emit-llvm</span> simple_file.c <span class="nt">-o</span> simple_file.ll
</code></pre></div></div>

<p>That will provide us with the next <code class="language-plaintext highlighter-rouge">LLVM IR</code> code:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">;</span><span class="w"> </span>ModuleID <span class="o">=</span> <span class="s1">'simple_file.c'</span>
<span class="go">source_filename = "simple_file.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

@.str = private unnamed_addr constant [26 x i8] c"This is just a test: %ld\0A\00", align 1

</span><span class="gp">;</span><span class="w"> </span>Function Attrs: noinline nounwind optnone uwtable
<span class="gp">define dso_local i64 @func(i64 noundef %0) #</span>0 <span class="o">{</span>
<span class="go">  %2 = alloca i64, align 8
  store i64 %0, ptr %2, align 8
  %3 = load i64, ptr %2, align 8
  %4 = add nsw i64 %3, 5
  %5 = add nsw i64 %4, 8
  ret i64 %5
}

</span><span class="gp">;</span><span class="w"> </span>Function Attrs: noinline nounwind optnone uwtable
<span class="gp">define dso_local i32 @main(i32 noundef %0, ptr noundef %1) #</span>0 <span class="o">{</span>
<span class="go">  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  %5 = alloca ptr, align 8
  store i32 0, ptr %3, align 4
  store i32 %0, ptr %4, align 4
  store ptr %1, ptr %5, align 8
  %6 = load i32, ptr %4, align 4
  %7 = sext i32 %6 to i64
  %8 = call i64 @func(i64 noundef %7)
  %9 = call i32 (ptr, ...) @printf(ptr noundef @.str, i64 noundef %8)
  %10 = load i32, ptr %4, align 4
  ret i32 %10
}

</span><span class="gp">declare i32 @printf(ptr noundef, ...) #</span>1
<span class="go">
</span><span class="gp">attributes #</span>0 <span class="o">=</span> <span class="o">{</span> noinline nounwind optnone uwtable <span class="s2">"frame-pointer"</span><span class="o">=</span><span class="s2">"all"</span> <span class="s2">"min-legal-vector-width"</span><span class="o">=</span><span class="s2">"0"</span> <span class="s2">"no-trapping-math"</span><span class="o">=</span><span class="s2">"true"</span> <span class="s2">"stack-protector-buffer-size"</span><span class="o">=</span><span class="s2">"8"</span> <span class="s2">"target-cpu"</span><span class="o">=</span><span class="s2">"x86-64"</span> <span class="s2">"target-features"</span><span class="o">=</span><span class="s2">"+cx8,+fxsr,+mmx,+sse,+sse2,+x87"</span> <span class="s2">"tune-cpu"</span><span class="o">=</span><span class="s2">"generic"</span> <span class="o">}</span>
<span class="gp">attributes #</span>1 <span class="o">=</span> <span class="o">{</span> <span class="s2">"frame-pointer"</span><span class="o">=</span><span class="s2">"all"</span> <span class="s2">"no-trapping-math"</span><span class="o">=</span><span class="s2">"true"</span> <span class="s2">"stack-protector-buffer-size"</span><span class="o">=</span><span class="s2">"8"</span> <span class="s2">"target-cpu"</span><span class="o">=</span><span class="s2">"x86-64"</span> <span class="s2">"target-features"</span><span class="o">=</span><span class="s2">"+cx8,+fxsr,+mmx,+sse,+sse2,+x87"</span> <span class="s2">"tune-cpu"</span><span class="o">=</span><span class="s2">"generic"</span> <span class="o">}</span>
<span class="go">
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"Ubuntu clang version 16.0.6 (++20230710042027+7cbf1a259152-1~exp1~20230710162048.105)"}
</span></code></pre></div></div>

<p>We just need to replace <code class="language-plaintext highlighter-rouge">@func</code> with any of the previously generated functions of <code class="language-plaintext highlighter-rouge">LLVM IR</code>, and compile it with the next command:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>clang-16 simple_file.ll <span class="nt">-o</span> simple_file
</code></pre></div></div>

<p>This binary can be run and also loaded in Ghidra for the analysis, in my case I have done different tests with compilation flags, and with the optimizations that Triton offers:</p>

<figure>
<a href="/assets/images/hacklu-ollvm/23.png"><img src="/assets/images/hacklu-ollvm/23.png" /></a>
<figcaption>Files generated with the LLVM IR code, and with different compiler flags.</figcaption>
</figure>

<p>And with this we can continue doing the analysis of the simplified codes, and also with this I conclude the post!</p>

<h3 id="extra">Extra</h3>

<p>Looking for the constants from the binary, I have found another interesting solution posted in <a href="https://hackmd.io/@crazyman/rke1hPpUF">here</a>, where the algorithm was reversed, and bruteforcing some of the parameters in the algorithm the correct input value can be calculated, while I think it does not exactly retrieves the inverse hash, it is another solution that would work. In the website, the provided code is for Windows, but next I provide a C++ version that it also works:</p>

<pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;unistd.h&gt;

std::uint64_t g_chunk_size = 0;

std::uint64_t g_jieguo = 0;
std::uint64_t g_chengshu = 0;

bool g_finded_low = false;
std::uint64_t g_find_val_low = 0;

bool g_finded_high = false;
std::uint64_t g_find_val_high = 0;

std::uint32_t CalcThread(void * start_v) {
  std::uint64_t ustartv = (std::uint64_t) start_v;
  std::uint32_t targetv = g_jieguo &amp; 0xFFFFFFFF;
  std::uint32_t chengshulow = g_chengshu &amp; 0xFFFFFFFF;
  for (std::uint64_t i = 0; i &lt; g_chunk_size; i++) {
    if (
      (((ustartv + i) * chengshulow) &amp; 0xFFFFFFFF) == targetv
    ) {
      g_find_val_low = (ustartv + i);
      g_finded_low = true;
    }
    if (g_finded_low)
      break;
  }
  return 0;
}
std::uint32_t CalcThreadHigh(void * start_v) {
  std::uint64_t ustartv = (std::uint64_t) start_v;
  for (std::uint64_t i = 0; i &lt; g_chunk_size; i++) {
    std::uint64_t vv = ((ustartv + i) &lt;&lt; 32) | (g_find_val_low);
    if (
      (vv * g_chengshu) == g_jieguo
    ) {
      g_find_val_high = (ustartv + i);
      g_finded_high = true;
    }
    if (g_finded_high)
      break;
  }
  return 0;
}

std::uint64_t findchengshu(std::uint64_t jieguo, std::uint64_t chengshu) {
  g_chengshu = chengshu;
  g_jieguo = jieguo;
  g_finded_low = 0;
  g_find_val_low = 0;
  g_finded_high = 0;
  g_find_val_high = 0;

  int heshu = 8;

  std::uint64_t block_size = (0x100000000 / heshu);
  g_chunk_size = block_size;
  for (int i = 0; i &lt; heshu; i++) {
    std::uint32_t tid = 0;
    CalcThread((void * )(block_size * i));
    ///CreateThread(0, 0, CalcThread, (void*)(block_size * i), 0, &amp;tid);
  }

  while (g_finded_low == false)
    sleep(10);

  for (int i = 0; i &lt; heshu; i++) {
    std::uint32_t tid = 0;
    CalcThreadHigh((void * )(block_size * i));
    ///CreateThread(0, 0, CalcThreadHigh, (void*)(block_size * i), 0, &amp;tid);
  }

  while (g_finded_high == false)
    sleep(10);
  return g_find_val_low | (((std::uint64_t) g_find_val_high) &lt;&lt; 32);
}
std::uint64_t reneg(std::uint64_t v) {
  return ~v + 1;
}
std::uint64_t re22(std::uint64_t v) {
  std::uint64_t _1 = v &amp; 0xFF;
  std::uint64_t _2 = (v &amp; 0xFF00) &gt;&gt; 8;
  std::uint64_t _3 = (v &amp; 0xFFFFFF) &gt;&gt; 16;
  std::uint64_t _4 = (v &amp; 0xFFFFFFFF) &gt;&gt; 24;
  std::uint64_t _5 = (v &amp; 0xFFFFFFFFFF) &gt;&gt; 32;
  std::uint64_t _6 = (v &amp; 0xFFFFFFFFFFFF) &gt;&gt; 40;
  std::uint64_t _7 = (v &amp; 0xFFFFFFFFFFFFFF) &gt;&gt; 48;
  std::uint64_t _8 = (v &amp; 0xFFFFFFFFFFFFFFFF) &gt;&gt; 56;

  return _2 | (_1 &lt;&lt; 8) | (_4 &lt;&lt; 16) | (_3 &lt;&lt; 24) | (_6 &lt;&lt; 32) | (_5 &lt;&lt; 40) | (_8 &lt;&lt; 48) | (_7 &lt;&lt; 56);

}
std::uint64_t re15(std::uint64_t v) {
  return ((v &amp; 0x00FFFFFFFFFFFFFF) &lt;&lt; 8) | (v &gt;&gt; 56);
}
std::uint64_t re9(std::uint64_t v) {
  std::uint64_t nv = ((v &gt;&gt; 32) &amp; 0xFFFFFFFF) | (v &lt;&lt; 32);

  return nv ^ 0xCE9A20C53746A9F7;
}
std::uint64_t invertVal(std::uint64_t v) {
  v = reneg(v);
  v = findchengshu(v, 0x51F6D71704B266F5);
  v = v ^ 0xB9B8A788569D772D;
  v = re22(v);
  v -= 0x29D5CA44D143B4FC;
  v ^= 0x326DEB9C5D995AEB;
  v = re15(v);
  v -= 0x18B205A73CB902B7;
  v = findchengshu(v, 0xA648BD40DACE4EF5);
  v = re9(v);
  v -= 0x8BC715D20D923835;
  v ^= 0xB31C9545AC410D72;
  v = reneg(v);
  v += 0x4DDB14EE5C8771C5;
  v = ~v + 1;

  return v;
}
std::uint64_t reval(std::uint64_t v) {
  std::uint64_t _1 = v &amp; 0xFF;
  std::uint64_t _2 = (v &amp; 0xFF00) &gt;&gt; 8;
  std::uint64_t _3 = (v &amp; 0xFFFFFF) &gt;&gt; 16;
  std::uint64_t _4 = (v &amp; 0xFFFFFFFF) &gt;&gt; 24;
  std::uint64_t _5 = (v &amp; 0xFFFFFFFFFF) &gt;&gt; 32;
  std::uint64_t _6 = (v &amp; 0xFFFFFFFFFFFF) &gt;&gt; 40;
  std::uint64_t _7 = (v &amp; 0xFFFFFFFFFFFFFF) &gt;&gt; 48;
  std::uint64_t _8 = (v &amp; 0xFFFFFFFFFFFFFFFF) &gt;&gt; 56;

  return _8 | (_7 &lt;&lt; 8) | (_6 &lt;&lt; 16) | (_5 &lt;&lt; 24) | (_4 &lt;&lt; 32) | (_3 &lt;&lt; 40) | (_2 &lt;&lt; 48) | (_1 &lt;&lt; 56);
}

int main() {
  std::uint64_t val[9];
  val[8] = 0;
  val[0] = reval(invertVal(0x875cd4f2e18f8fc4));
  val[1] = reval(invertVal(0xbb093e17e5d3fa42));
  val[2] = reval(invertVal(0xada5dd034aae16b4));
  val[3] = reval(invertVal(0x97322728fea51225));
  val[4] = reval(invertVal(0x4124799d72188d0d));
  val[5] = reval(invertVal(0x2b3e3fbbb4d44981));
  val[6] = reval(invertVal(0xdfcac668321e4daa));
  val[7] = reval(invertVal(0xeac2137a35c8923a));
  printf("%s\n", val);
}
</code></pre>

<h2 id="conclusions">Conclusions</h2>

<p>This challenge was interesting to discover other obfuscations, I have also learned other features from Triton, and I thought it was useful for a second post. I hope you have enjoyed the post and see you in the next one space cowboy!</p>

<figure>
<a href="/assets/images/hacklu-ollvm/seeu.jpeg"><img src="/assets/images/hacklu-ollvm/seeu.jpeg" /></a>
</figure>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Symbolic Execution" /><category term="Triton" /><category term="Python" /><category term="C++" /><category term="ELF" /><category term="Linux" /><category term="Binary Analysis" /><summary type="html"><![CDATA[Following the previous post about using Triton for solving challenges through symbolic execution and SMT Solving, this time we will try solving an obfuscated hacklu.]]></summary></entry><entry><title type="html">Solving Hex-Rays Challenge with Triton and TritonDSE</title><link href="https://fare9.github.io/symbolic%20execution/triton/hexrays-challenge-triton/" rel="alternate" type="text/html" title="Solving Hex-Rays Challenge with Triton and TritonDSE" /><published>2023-06-26T00:00:00+00:00</published><updated>2023-06-28T10:40:00+00:00</updated><id>https://fare9.github.io/symbolic%20execution/triton/hexrays-challenge-triton</id><content type="html" xml:base="https://fare9.github.io/symbolic%20execution/triton/hexrays-challenge-triton/"><![CDATA[<figure>
<a href="/assets/images/hex-ray-challenge/cover.png"><img src="/assets/images/hex-ray-challenge/cover.png" /></a>
</figure>

<p>A few weeks ago, Robert Yates uploaded a <a href="https://twitter.com/yates82/status/1662440679459500033">tweet</a> featuring a video solving a challenge by the company Hex-Rays with the use of <a href="https://binary.ninja/">Binary Ninja</a> and the <a href="https://github.com/borzacchiello/seninja">SENinja</a> plugin. Inspired by this, I decided to embark on a similar journey, but this time using <a href="https://triton-library.github.io/">Triton</a> and later incorporating <a href="https://blog.quarkslab.com/introducing-tritondse-a-framework-for-dynamic-symbolic-execution-in-python.html">TritonDSE</a>. These two libraries provide powerful capabilities for Dynamic Symbolic Execution (DSE). Triton, written in C++, offers a Python API that makes it easy to work with. TritonDSE, on the other hand, is a Python library built on top of Triton, which provides DSE capabilities in a more accessible manner, along with other useful features such as program loading. For the disassembly and decompilation tasks, I will be using <a href="https://ghidra-sre.org/">Ghidra</a>, an open-source disassembler/decompiler written in Java and released by the NSA.</p>

<h2 id="authors">Authors</h2>

<ul>
  <li>Eduardo Blazquez</li>
</ul>

<h2 id="the-challenge">The Challenge</h2>

<p>The challenge is an ELF binary for 64-bit architecture, dynamically linked, and has a size of 1.4 Mega bytes. We can obtain this information using the following command:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>file challenge
<span class="go">challenge: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=83db7b297901c743a71f43e813e3dc266245b220, for GNU/Linux 3.2.0, stripped
</span><span class="gp">$</span><span class="w"> </span><span class="nb">ls</span> <span class="nt">-lah</span> challenge
<span class="go">-rwxrwxr-x 1 symbolic symbolic 1.4M May 17 09:55 challenge
</span></code></pre></div></div>

<p>The program requires one argument to run, so we assume that it expects a specific flag or input. Our task is to find the correct flag to successfully execute the program. Let’s give it a try. When we run the program without providing any argument, we receive a message asking for a password. As an initial attempt, I’ll enter part of the name of a song by Rainbow: “Temple of the King”. Here’s what I got:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/1.png"><img src="/assets/images/hex-ray-challenge/1.png" /></a>
<figcaption>Running the binary with a password, and with an incorrect password.</figcaption>
</figure>

<p>From the program’s output, we can see that it renders a PNG file, indicating that my initial approach was incorrect. It seems like I need to look for the password in a different place (or maybe the program just doesn’t appreciate Dio’s song…).</p>

<p>Instead of using other tools for analysis, I’ll directly open the binary in a disassembler. As mentioned earlier, I’ll be using Ghidra for this challenge.</p>

<h3 id="analyzing-the-challenge-with-ghidra">Analyzing the Challenge with Ghidra</h3>

<p>To analyze the binary using Ghidra’s disassembler and decompiler, we need to create a project in the tool. If you haven’t already done so, you can follow the instructions in the Ghidra documentation or refer to beginner’s tutorials to learn how to create a project (or if you want to dig deeper, I recommend you any of the next books <a href="https://www.packtpub.com/product/ghidra-software-reverse-engineering-for-beginners/9781800207974">Ghidra Software Reverse Engineering for Beginners</a>, or <a href="https://www.ghidrabook.com/">The Ghidra Book: The Definitive Guide</a>).</p>

<p>Once the project is created, we can load the binary into Ghidra. This can be done by selecting “File” -&gt; “Import File” and choosing the binary file. Ghidra will analyze the binary and present you with the main project screen.</p>

<p>In the project screen, you will see various panels and tabs that provide different views of the disassembled code, decompiled code, and other program information. The main panel typically displays the disassembled code, and you can navigate through the different functions and sections of the binary.</p>

<p>To gain a better understanding of the code, we can use the decompiler view alongside the disassembler. The decompiler translates the assembly code into a higher-level language representation, making it easier to comprehend the logic of the program. You can switch to the decompiler view by selecting the appropriate tab or panel in Ghidra.</p>

<p>Using both the disassembler and decompiler views, we can examine the code, identify important functions or operations related to password handling, and trace the program’s execution flow.</p>

<p>It’s worth mentioning that while the decompiler provides a more readable representation, there may be cases where it struggles to accurately represent complex or obfuscated code. In such cases, referring back to the disassembled code can provide additional insights.</p>

<p>By carefully analyzing the disassembled and decompiled code, we can uncover the password validation mechanism and continue our journey to solve the challenge.</p>

<figure>
<a href="/assets/images/hex-ray-challenge/2.png"><img src="/assets/images/hex-ray-challenge/2.png" /></a>
<figcaption>Ghidra project and loaded binary.</figcaption>
</figure>

<p>When we open the binary in Ghidra and click on it, Ghidra will automatically take us to the <code class="language-plaintext highlighter-rouge">main</code> function. The <code class="language-plaintext highlighter-rouge">main</code> function is typically the entry point of the program, where the execution starts.</p>

<p>However, if we were analyzing a binary where the entry point is not the <code class="language-plaintext highlighter-rouge">main</code> function, Ghidra would instead take us to the <code class="language-plaintext highlighter-rouge">entry</code> function. The <code class="language-plaintext highlighter-rouge">entry</code> function is a special function generated by the compiler and serves as the initial entry point specified in the ELF header (<code class="language-plaintext highlighter-rouge">e_entry</code> value).</p>

<p>In the <code class="language-plaintext highlighter-rouge">entry</code> function, we would usually see a call to the <code class="language-plaintext highlighter-rouge">__libc_start_main</code> function. The <code class="language-plaintext highlighter-rouge">__libc_start_main</code> function is part of the C runtime library and sets up the necessary environment for executing the program. The first argument (<code class="language-plaintext highlighter-rouge">RDI</code> register) passed to <code class="language-plaintext highlighter-rouge">__libc_start_main</code> is typically the address of the <code class="language-plaintext highlighter-rouge">main</code> function.</p>

<p>By following the function calls and analyzing the code, we can understand the flow of the program and identify the relevant parts for our analysis, such as the password validation logic or any other functionality we are interested in.</p>

<figure>
<a href="/assets/images/hex-ray-challenge/3.png"><img src="/assets/images/hex-ray-challenge/3.png" /></a>
<figcaption>Entry function of the binary.</figcaption>
</figure>

<p>If we double click into the word <code class="language-plaintext highlighter-rouge">main</code> we will directly go to the <code class="language-plaintext highlighter-rouge">main</code> function, in my case I already renamed variables, and also I have changed the signature of the function, something you can do clicking on function’s name and pressing <code class="language-plaintext highlighter-rouge">F</code>.</p>

<figure>
<a href="/assets/images/hex-ray-challenge/4.png"><img src="/assets/images/hex-ray-challenge/4.png" /></a>
<figcaption>Main function of the binary.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/5.png"><img src="/assets/images/hex-ray-challenge/5.png" /></a>
<figcaption>Screen where we can change function's signature.</figcaption>
</figure>

<p>If later you want to rename variables remember that in Ghidra you have to click on variable’s name, and then press <code class="language-plaintext highlighter-rouge">L</code>, or for leaving a comment, you have to press <code class="language-plaintext highlighter-rouge">;</code>.</p>

<p>By skipping the prologue of the function, we are able to directly encounter a few calls to what appears to be the API of the <a href="https://www.libsdl.org/"><em>SDL</em></a> library. This library is utilized to provide access to hardware and graphics functionalities, making it particularly useful for rendering images and commonly employed in video games. Additionally, we observe the initial check of the <code class="language-plaintext highlighter-rouge">argc</code> value, ensuring that it is greater than 1. Otherwise, the program proceeds to the error code. Below, you’ll find both the assembly code and the decompiled code from Ghidra, accompanied by comments and renamed variables:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/6.png"><img src="/assets/images/hex-ray-challenge/6.png" /></a>
<figcaption>Beginning part of the function in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/7.png"><img src="/assets/images/hex-ray-challenge/7.png" /></a>
<figcaption>Beginning part of the function in pseudo-C.</figcaption>
</figure>

<p>As we further analyze the code, we come across a section that is highly optimized in assembly, but in the pseudo-code representation provided by Ghidra, it appears to be the initialization of a large array. The code might have been generated using a <code class="language-plaintext highlighter-rouge">memset</code> function, but internally the compiler generates assembly code that utilizes the <code class="language-plaintext highlighter-rouge">xmm0</code> register. This register is set to 0 using an <code class="language-plaintext highlighter-rouge">xor</code> operation and then used to initialize the first 16 bytes of a buffer. Additionally, we observe an initialization of byte 16 to 24 to 0. Finally, a call to <code class="language-plaintext highlighter-rouge">strncpy</code> is made, copying the contents from <code class="language-plaintext highlighter-rouge">argv[1]</code> to the initialized buffer. By considering these details, we can infer that this section is responsible for initializing a local buffer and copying the contents of <code class="language-plaintext highlighter-rouge">argv[1]</code> into it. In Ghidra, we can set the type of the buffer by pressing the ‘Y’ key and selecting the appropriate type. In my case, I chose the type <code class="language-plaintext highlighter-rouge">uint[0x18]</code>. We could even easily implement it in C:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">char</span> <span class="n">internal_buffer</span><span class="p">[</span><span class="mh">0x18</span><span class="p">];</span>
    <span class="p">...</span>
    <span class="n">memset</span><span class="p">(</span><span class="n">internal_buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">);</span>
    <span class="n">strncpy</span><span class="p">(</span><span class="n">internal_buffer</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="mh">0x18</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>But with Ghidra we will find something like the next:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/8.png"><img src="/assets/images/hex-ray-challenge/8.png" /></a>
<figcaption>Initialization of the local buffer in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/9.png"><img src="/assets/images/hex-ray-challenge/9.png" /></a>
<figcaption>Initialization of the local buffer in pseudo-C.</figcaption>
</figure>

<h3 id="getting-started-with-the-mathematics">Getting Started with the Mathematics</h3>

<p>Given that I’m using a DSE engine with a solver like Z3, it’s likely that readers have already realized that this challenge involves solving mathematical equations. It’s important to note that attempting to solve these equations manually would be both time-consuming and extremely difficult. In this section, we will examine the various equations present in the program and attempt to represent them. Through this exploration, we will gain a deeper understanding of why these equations play a crucial role in solving the challenge.</p>

<h4 id="equation-1">Equation 1</h4>

<p>Following the <code class="language-plaintext highlighter-rouge">strncpy</code> call, we encounter the first equation that needs to be solved. Additionally, these initial constraints will be used to provide input to Z3, ensuring the challenge is correctly solved. The following images depict the first equation:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/10.png"><img src="/assets/images/hex-ray-challenge/10.png" /></a>
<figcaption>First equation and first constraint in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/11.png"><img src="/assets/images/hex-ray-challenge/11.png" /></a>
<figcaption>First equation and first constraint in pseudo-C.</figcaption>
</figure>

<p>We have the first equation with the first constraint in this pseudo code:</p>

<h:math>
(password[16:18] + password[22:24]) - (password[8:10] + password[14:16]) = 0x1cd4
</h:math>

<p><br /></p>

<h4 id="equation-2">Equation 2</h4>

<p>So, we have established the first constraint, which means that Z3 needs to select values that fulfill the condition of obtaining the result <code class="language-plaintext highlighter-rouge">0x1cd4</code> for the previous operation.</p>

<p>Now, let’s move on to the second equation and the corresponding constraint, which is located right below the previously discussed code.</p>

<figure>
<a href="/assets/images/hex-ray-challenge/12.png"><img src="/assets/images/hex-ray-challenge/12.png" /></a>
<figcaption>Second equation and second constraint in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/13.png"><img src="/assets/images/hex-ray-challenge/13.png" /></a>
<figcaption>Second equation and second constraint in pseudo-C.</figcaption>
</figure>

<p>Let’s represent as I did before, the equation with a more mathematical notation:</p>

<h:math>
(password[6:8] + password[2:4] + password[20:22]) - password[10:12] = 0xd899 
</h:math>

<p><br /></p>

<p>Again, once we feed Z3 with this constrait, it will have to find another 4 values (again 8 bytes, because each value are <code class="language-plaintext highlighter-rouge">word</code> size) which solve the equation. In case any of the previous equations do not work, we will go to a code that will render the error PNG, and will apply a cleanup:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/14.png"><img src="/assets/images/hex-ray-challenge/14.png" /></a>
<figcaption>Error code in case any of the first or second equation are not correct.</figcaption>
</figure>

<h4 id="equation-3-and-first-decryption-loop">Equation 3 and first decryption loop</h4>

<p>We will move following the <code class="language-plaintext highlighter-rouge">JZ</code> instruction and we can see the third equation:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/15.png"><img src="/assets/images/hex-ray-challenge/15.png" /></a>
<figcaption>Third equation and third constraint in assembly.</figcaption>
</figure>

<p>We obtain the next equation in a mathematical notation:</p>

<h:math>
password[16:24] &oplus; password[0:8] = 0xa04233a475d1b72
</h:math>

<p><br /></p>

<p>Once again, we will utilize this equation as a constraint for the bytes used by Z3. If this condition is not satisfied, the program would branch to the error code. However, if we provide the correct values, we would enter the first decryption loop.</p>

<p>The challenge includes an encrypted PNG file that will be decrypted using the provided password. Even if we attempt to bypass the jump instructions without correctly solving the challenge, we will not obtain the correct PNG. Assuming we have reached this point without bypassing any jumps and have provided the correct password so far, we will encounter the following code:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/16.png"><img src="/assets/images/hex-ray-challenge/16.png" /></a>
<figcaption>First decryption loop in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/17.png"><img src="/assets/images/hex-ray-challenge/17.png" /></a>
<figcaption>First decryption loop in pseudo-C.</figcaption>
</figure>

<p>Although Ghidra is capable of generating decompiled code, it may appear somewhat unconventional and involve complex mathematical operations. In this case, I suggest referring to the assembly code, which tends to be clearer. The algorithm consists of a loop that performs a decryption operation using a portion of our password as the key. This aspect of the challenge makes it more difficult, as we need to find the correct password that successfully decrypts the PNG file. <strong>It’s important to remember the addresses of the decryption loop, as it is not relevant for symbolic execution, and bypassing it will save time and memory!</strong></p>

<h4 id="equation-4-and-second-decryption-loop">Equation 4 and second decryption loop</h4>

<p>Once we step out the first decryption loop, we will have the fourth equation in the code, we can see its assembly and its pseudo-C in the next pictures:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/18.png"><img src="/assets/images/hex-ray-challenge/18.png" /></a>
<figcaption>Fourth equation and constraint in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/19.png"><img src="/assets/images/hex-ray-challenge/19.png" /></a>
<figcaption>Fourth equation and constraint in pseudo-C.</figcaption>
</figure>

<p>Once again, we will use this equation as a constraint for Z3 to derive additional portions of the password and ultimately obtain the correct password. Here is the equation used in this section of the code:</p>

<h:math>
((password[0:4] * 2 + password[20:24]) - (password[8:12]*4)) - (password[16:20] &gt;&gt; 3) - (password[4:8] &gt;&gt; 3) = 0x4b5469c
</h:math>

<p><br /></p>

<p>Similarly to the previous sections, if the computation using the provided password does not yield the value <code class="language-plaintext highlighter-rouge">0x4b5469c</code>, we will be redirected to the error code, which displays an error PNG. However, if the correct password is supplied, we will directly jump to the second decryption loop.</p>

<figure>
<a href="/assets/images/hex-ray-challenge/20.png"><img src="/assets/images/hex-ray-challenge/20.png" /></a>
<figcaption>Second decryption loop in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/21.png"><img src="/assets/images/hex-ray-challenge/21.png" /></a>
<figcaption>Second decryption loop in pseudo-C.</figcaption>
</figure>

<p>Again we have a decryption loop that uses the provided password from the user for decrypting the correct PNG. Again we would be working with a symbolic variable (I’ll show it in Triton’s part), for that reason what we will do is just step out and jump over this decryption loop. <strong>Keep these addresses too for the symbolic execution</strong>.</p>

<h4 id="last-equation">Last Equation</h4>

<p>Once we have finished the second decryption loop we arrive to the final check applied in the program, this will be the last constraint our solver will need for obtaining the password, in the next pictures we can see the last equation, while we cannot see where R8 comes from and which value is used in the assembly, in the decompiled part we can see what addresses are <code class="language-plaintext highlighter-rouge">xored</code>.</p>

<figure>
<a href="/assets/images/hex-ray-challenge/22.png"><img src="/assets/images/hex-ray-challenge/22.png" /></a>
<figcaption>Last equation in assembly.</figcaption>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/23.png"><img src="/assets/images/hex-ray-challenge/23.png" /></a>
<figcaption>Last equation in pseudo-C.</figcaption>
</figure>

<p>And here in a mathematical format as before:</p>

<h:math>
password[16:24] &oplus; passwords[8:16] = 0x231f0b21595d0455
</h:math>

<p><br /></p>

<p>With this part we would have finished the analysis of the equations and the constraints, we just leave from the program the next code:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/24.png"><img src="/assets/images/hex-ray-challenge/24.png" /></a>
</figure>

<figure>
<a href="/assets/images/hex-ray-challenge/25.png"><img src="/assets/images/hex-ray-challenge/25.png" /></a>
</figure>

<p>This part of the code just apply a final decryption, and finally it shows the image to the user, so we do not need to know anything more from the challenge for solving it.</p>

<p>Here are all the equations combined:</p>

<h:math>
(password[16:18] + password[22:24]) - (password[8:10] + password[14:16]) = 0x1cd4
<br />
(password[6:8] + password[2:4] + password[20:22]) - password[10:12] = 0xd899 
<br />
password[16:24] &oplus; password[0:8] = 0xa04233a475d1b72
<br />
((password[0:4] * 2 + password[20:24]) - (password[8:12]*4)) - (password[16:20] &gt;&gt; 3) - (password[4:8] &gt;&gt; 3) = 0x4b5469c
<br />
password[16:24] &oplus; passwords[8:16] = 0x231f0b21595d0455
</h:math>

<p><br /></p>

<p>These equations represent the constraints that need to be satisfied in order to find the correct password for the challenge. By solving these equations, we can obtain the values for the corresponding parts of the password that will successfully decrypt the PNG file.</p>

<h2 id="solving-the-challenge-with-triton">Solving the Challenge With Triton</h2>

<figure>
<a href="/assets/images/hex-ray-challenge/triton.png"><img src="/assets/images/hex-ray-challenge/triton.png" style="background-color:white;" /></a>
</figure>

<p>As stated on its <a href="https://triton-library.github.io/">website</a>, Triton is a dynamic binary analysis library that provides internal components to build program analysis tools, automate reverse engineering, perform software verification, or emulate code.</p>

<p>The website also presents the architecture of Triton, which includes the following components:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/triton_arch.png"><img src="/assets/images/hex-ray-challenge/triton_arch.png" /></a>
</figure>

<p>What we will do with Triton is emulate the code and set part of the memory as symbolic. When Triton runs the program’s code, it creates expressions using the symbolic variables, and we can retrieve an Abstract Syntax Tree (AST) representation from these expressions. We will apply different constraints to the expressions and use Z3 to solve them and obtain the password. The following steps will be followed:</p>

<ol>
  <li>Create hooks for different library functions that are not implemented in Triton.</li>
  <li>Analyze the binary using Lief.</li>
  <li>Load the binary.</li>
  <li>Emulate the binary, applying library hooks and our own hooks.</li>
  <li>Apply constraints at specific points.</li>
  <li>Solve the final expression with the constraints.</li>
</ol>

<p>In this part of the blog, I will include excerpts from the scripts. You can find the complete code of the script <a href="https://github.com/Fare9/My-Symbolic-Execution/blob/master/IDA-challenge/free-madame-de-maintenon-challenge/triton_solver.py">here</a>.</p>

<p>Triton is primarily focused on analysis, so tasks like loading the binary, applying relocations, or allocating memory are not automatically handled by the library and are left to the analyst. The implementation of standard functions is also the analyst’s responsibility. However, Triton provides examples of these functions on its website. In the following sections, we will explore some of these functions and then proceed with the code for solving the challenge.</p>

<h3 id="creating-hooks-for-library-functions">Creating Hooks for Library Functions</h3>

<p>First, let’s see how to create a hook for the function <code class="language-plaintext highlighter-rouge">__libc_start_main</code>, in this function we will provide the code for giving the arguments to the program, the next code will be used in almost all the Triton scripts:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">libc_start_main</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'[+] __libc_start_main hooked'</span><span class="p">)</span>

    <span class="c1"># Get arguments
</span>    <span class="n">main</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">)</span>

    <span class="c1"># Push the return value to jump into the main() function
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">)</span><span class="o">-</span><span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">)</span>

    <span class="c1"># set as return value the address of main
</span>    <span class="c1"># avoid all the libc stuff
</span>    <span class="n">ret2main</span> <span class="o">=</span> <span class="n">MemoryAccess</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">),</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">)</span>
    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">ret2main</span><span class="p">,</span> <span class="n">main</span><span class="p">)</span>

    <span class="c1"># Setup argc / argv
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">concretizeRegister</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">)</span>
    <span class="n">ctx</span><span class="p">.</span><span class="n">concretizeRegister</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">)</span>

    <span class="c1"># here write all the needed arguments
</span>    <span class="n">argvs</span> <span class="o">=</span> <span class="p">[</span>
        <span class="nb">bytes</span><span class="p">(</span><span class="n">TARGET</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)),</span>  <span class="c1"># argv[0]
</span>        <span class="sa">b</span><span class="s">'A'</span><span class="o">*</span><span class="mh">0x18</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'</span><span class="se">\00</span><span class="s">'</span>
    <span class="p">]</span>

    <span class="c1"># Define argc / argv
</span>    <span class="n">base</span>  <span class="o">=</span> <span class="n">BASE_ARGV</span>
    <span class="n">addrs</span> <span class="o">=</span> <span class="nb">list</span><span class="p">()</span>

    <span class="c1"># create the arguments
</span>    <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">argv</span> <span class="ow">in</span> <span class="n">argvs</span><span class="p">:</span>
        <span class="n">addrs</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
        <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">argv</span><span class="o">+</span><span class="sa">b</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">)</span>
        <span class="n">base</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">argv</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span>
        <span class="k">print</span><span class="p">(</span><span class="s">'[+] argv[%d] = %s'</span> <span class="o">%</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">argv</span><span class="p">))</span>
        <span class="n">index</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="c1"># set the pointer to the arguments
</span>    <span class="n">argc</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">argvs</span><span class="p">)</span>
    <span class="n">argv</span> <span class="o">=</span> <span class="n">base</span>
    <span class="k">for</span> <span class="n">addr</span> <span class="ow">in</span> <span class="n">addrs</span><span class="p">:</span>
        <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">MemoryAccess</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">),</span> <span class="n">addr</span><span class="p">)</span>
        <span class="n">base</span> <span class="o">+=</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span>

    <span class="c1"># finally set RDI and RSI values
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">,</span> <span class="n">argc</span><span class="p">)</span>
    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">,</span> <span class="n">argv</span><span class="p">)</span>

    <span class="k">return</span> <span class="p">(</span><span class="n">CONCRETE</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</code></pre></div></div>

<p>We will also create a hook for the <code class="language-plaintext highlighter-rouge">strncpy</code> function. This function is used to copy the argument <code class="language-plaintext highlighter-rouge">argv[1]</code> into a local buffer in the stack, which represents the password provided by the user. Since we want to calculate this buffer, we will set it as <em>symbolic</em>. This will allow us to apply symbolic execution and obtain the different expressions associated with it.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">strncpy</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">MEM_ADDRESS_BUFFER</span>

    <span class="k">print</span><span class="p">(</span><span class="s">"[+] strncpy hooked"</span><span class="p">)</span>
    <span class="c1"># get rdi the first argument to be hooked
</span>    <span class="n">rdi</span> <span class="o">=</span> <span class="n">triton_ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdi</span><span class="p">)</span>

    <span class="k">print</span><span class="p">(</span><span class="s">"Symbolizing the user input in the address 0x%08X"</span> <span class="o">%</span> <span class="n">rdi</span><span class="p">)</span>

    <span class="c1"># save the value
</span>    <span class="n">MEM_ADDRESS_BUFFER</span> <span class="o">=</span> <span class="n">rdi</span>

    <span class="c1"># because we want the password to have only ASCII values,
</span>    <span class="c1"># retrieve the minimum possible value
</span>    <span class="c1"># and the maximum value 
</span>    <span class="n">valid_characters</span> <span class="o">=</span> <span class="s">"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!</span><span class="se">\"</span><span class="s">#$%&amp;</span><span class="se">\'</span><span class="s">()*+,-./:;&lt;=&gt;?@[</span><span class="se">\\</span><span class="s">]^_`{|}~"</span>
    <span class="n">min_value</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">valid_characters</span><span class="p">))</span>
    <span class="n">max_value</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">valid_characters</span><span class="p">))</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mh">0x18</span><span class="p">):</span>
        <span class="n">memory_byte</span> <span class="o">=</span> <span class="n">MemoryAccess</span><span class="p">(</span><span class="n">rdi</span><span class="o">+</span><span class="n">i</span><span class="p">,</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">BYTE</span><span class="p">)</span>
        <span class="c1"># set first a concrete value (concolic)
</span>        <span class="n">triton_ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">memory_byte</span><span class="p">,</span> <span class="mi">61</span><span class="p">)</span>
        <span class="c1"># symbolize the memory address for extracting the expression
</span>        <span class="n">triton_ctx</span><span class="p">.</span><span class="n">symbolizeMemory</span><span class="p">(</span><span class="n">memory_byte</span><span class="p">,</span> <span class="s">"flag_%d"</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span><span class="p">))</span>
        <span class="c1"># add the ascii string constraints
</span>        <span class="n">triton_ctx</span><span class="p">.</span><span class="n">pushPathConstraint</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">.</span><span class="n">getMemoryAst</span><span class="p">(</span><span class="n">memory_byte</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="n">min_value</span><span class="p">)</span>
        <span class="n">triton_ctx</span><span class="p">.</span><span class="n">pushPathConstraint</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">.</span><span class="n">getMemoryAst</span><span class="p">(</span><span class="n">memory_byte</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="n">max_value</span><span class="p">)</span>

    <span class="c1"># finally set a 0 value (end of string)
</span>    <span class="n">triton_ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">MemoryAccess</span><span class="p">(</span><span class="n">rdi</span><span class="o">+</span><span class="mh">0x18</span><span class="p">,</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">BYTE</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span>
    <span class="c1"># return the strncpy value as a concrete value
</span>    <span class="k">return</span> <span class="p">(</span><span class="n">CONCRETE</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)</span>
</code></pre></div></div>

<p>HHere I have already added some constraints. Since we want a password with ASCII values, we will add two constraints for each value. The value must be greater than or equal to the minimum ASCII value for characters, and less than or equal to the maximum ASCII value for characters. To set the memory as symbolic, we use <code class="language-plaintext highlighter-rouge">symbolizeMemory</code>, and to create a constraint, we use <code class="language-plaintext highlighter-rouge">pushPathConstraint</code>. As symbolic execution can be computationally expensive, we concretize that memory with a concrete value, in this case, the value <code class="language-plaintext highlighter-rouge">A</code>. This technique is known as <em>Concolic Execution</em>.</p>

<p>Finally, we will have a structure that we will use to call these hooks, along with a function that will invoke the hooks during emulation. The code for this is as follows:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># the third value will be assigned during relocation.
</span><span class="n">customRelocation</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">[</span><span class="s">'strncpy'</span><span class="p">,</span> <span class="n">strncpy</span><span class="p">,</span> <span class="bp">None</span><span class="p">],</span>
    <span class="p">[</span><span class="s">'__libc_start_main'</span><span class="p">,</span> <span class="n">libc_start_main</span><span class="p">,</span> <span class="bp">None</span><span class="p">]</span>
<span class="p">]</span>

<span class="p">...</span>

<span class="k">def</span> <span class="nf">hookingHandler</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="s">'''
    In case one of the run address is one from
    the emulated functions, just call it and
    get the result, check if it's needed to symbolize
    the output register.

    :param ctx: Triton's context for emulation.
    '''</span>
    <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">rel</span> <span class="ow">in</span> <span class="n">customRelocation</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">rel</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">pc</span><span class="p">:</span>
            <span class="c1"># Emulate the routine and the return value
</span>            <span class="n">state</span><span class="p">,</span> <span class="n">ret_value</span> <span class="o">=</span> <span class="n">rel</span><span class="p">[</span><span class="mi">1</span><span class="p">](</span><span class="n">ctx</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">ret_value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
                <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rax</span><span class="p">,</span> <span class="n">ret_value</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">state</span> <span class="ow">is</span> <span class="n">SYMBOLIC</span><span class="p">:</span>
                    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'[+] Symbolizing the return value'</span><span class="p">)</span>
                    <span class="n">ctx</span><span class="p">.</span><span class="n">symbolizeRegister</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rax</span><span class="p">)</span>
            <span class="c1"># Get the return address
</span>            <span class="n">ret_addr</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteMemoryValue</span><span class="p">(</span><span class="n">MemoryAccess</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">),</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">))</span>
            <span class="c1"># Hijack RIP to skip the call
</span>            <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">,</span> <span class="n">ret_addr</span><span class="p">)</span>
            <span class="c1"># Restore RSP (simulate the ret)
</span>            <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">)</span><span class="o">+</span><span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">)</span>
    <span class="k">return</span>
</code></pre></div></div>

<h3 id="analyzing-and-loading-binary">Analyzing and Loading Binary</h3>

<p>For obtaining binary structure, we will use <em>Lief</em>, a parser library that will allow us to obtain information like sections from the binary, relocations, and so on. Then we will load the binary into memory for doing the analysis. First, we will write some constants with the memory structure we want for the binary:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Memory mapping
</span><span class="n">BASE_PLT</span>   <span class="o">=</span> <span class="mh">0x10000000</span>
<span class="n">BASE_ARGV</span>  <span class="o">=</span> <span class="mh">0x20000000</span>
<span class="n">BASE_STACK</span> <span class="o">=</span> <span class="mh">0x9ffffff0</span>
<span class="n">ERRNO</span>      <span class="o">=</span> <span class="mh">0xa0000000</span>
</code></pre></div></div>

<p>Then we need a code that goes section by section loading the binary into memory:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">loadBinary</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">,</span> <span class="n">lief_binary</span><span class="p">):</span>
    <span class="n">phdrs</span> <span class="o">=</span> <span class="n">lief_binary</span><span class="p">.</span><span class="n">segments</span>
    <span class="k">for</span> <span class="n">phdr</span> <span class="ow">in</span> <span class="n">phdrs</span><span class="p">:</span>
        <span class="n">size</span>    <span class="o">=</span> <span class="n">phdr</span><span class="p">.</span><span class="n">physical_size</span>
        <span class="n">vaddr</span>   <span class="o">=</span> <span class="n">phdr</span><span class="p">.</span><span class="n">virtual_address</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[+] Loading 0x%06x - 0x%06x"</span> <span class="o">%</span> <span class="p">(</span><span class="n">vaddr</span><span class="p">,</span> <span class="n">vaddr</span><span class="o">+</span><span class="n">size</span><span class="p">))</span>
        <span class="n">triton_ctx</span><span class="p">.</span><span class="n">setConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">vaddr</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">phdr</span><span class="p">.</span><span class="n">content</span><span class="p">))</span>
    <span class="k">return</span>
</code></pre></div></div>

<p>And finally, we need to apply relocations from the functions in the PLT, we will use the addresses from the imported functions to set the last values from <code class="language-plaintext highlighter-rouge">customRelocation</code> structure:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">makeRelocation</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">binary</span><span class="p">):</span>
    <span class="c1"># Setup plt
</span>    <span class="k">print</span><span class="p">(</span><span class="s">"[+] Applying relocations and extracting the addresses for the external functions"</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">pltIndex</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">customRelocation</span><span class="p">)):</span>
        <span class="n">customRelocation</span><span class="p">[</span><span class="n">pltIndex</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">BASE_PLT</span> <span class="o">+</span> <span class="n">pltIndex</span>

    <span class="n">relocations</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">binary</span><span class="p">.</span><span class="n">pltgot_relocations</span><span class="p">]</span>
    <span class="n">relocations</span><span class="p">.</span><span class="n">extend</span><span class="p">([</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">binary</span><span class="p">.</span><span class="n">dynamic_relocations</span><span class="p">])</span>

    <span class="c1"># Perform our own relocations
</span>    <span class="k">for</span> <span class="n">rel</span> <span class="ow">in</span> <span class="n">relocations</span><span class="p">:</span>
        <span class="n">symbolName</span> <span class="o">=</span> <span class="n">rel</span><span class="p">.</span><span class="n">symbol</span><span class="p">.</span><span class="n">name</span>
        <span class="n">symbolRelo</span> <span class="o">=</span> <span class="n">rel</span><span class="p">.</span><span class="n">address</span>
        <span class="k">for</span> <span class="n">crel</span> <span class="ow">in</span> <span class="n">customRelocation</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">symbolName</span> <span class="o">==</span> <span class="n">crel</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">'[+] Init PLT for: %s'</span> <span class="o">%</span><span class="p">(</span><span class="n">symbolName</span><span class="p">))</span>
                <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteMemoryValue</span><span class="p">(</span><span class="n">MemoryAccess</span><span class="p">(</span><span class="n">symbolRelo</span><span class="p">,</span> <span class="n">CPUSIZE</span><span class="p">.</span><span class="n">QWORD</span><span class="p">),</span> <span class="n">crel</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
                <span class="k">break</span>
    <span class="k">return</span>
</code></pre></div></div>

<h3 id="emulate-the-binary">Emulate the Binary</h3>

<p>First of all we can create a <code class="language-plaintext highlighter-rouge">run</code> function that will initialize the stack registers (<code class="language-plaintext highlighter-rouge">RBP</code> and <code class="language-plaintext highlighter-rouge">RSP</code>) creating a <em>fake stack</em>, and that function will call the emulation one:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">,</span> <span class="n">binary</span><span class="p">):</span>
    <span class="c1"># define a fake stack
</span>    <span class="n">triton_ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rbp</span><span class="p">,</span> <span class="n">BASE_STACK</span><span class="p">)</span>
    <span class="n">triton_ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">,</span> <span class="n">BASE_STACK</span><span class="p">)</span>

    <span class="c1"># Emulate binary from the entry point
</span>    <span class="k">print</span><span class="p">(</span><span class="s">"[+] Starting emulation from entry point 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">binary</span><span class="p">.</span><span class="n">entrypoint</span><span class="p">))</span>
    <span class="n">d1</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
    <span class="n">emulate</span><span class="p">(</span><span class="n">triton_ctx</span><span class="p">,</span> <span class="n">binary</span><span class="p">.</span><span class="n">entrypoint</span><span class="p">)</span>
    <span class="n">d2</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[+] Emulation finished."</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Time emulation: %.2f milliseconds"</span> <span class="o">%</span> <span class="p">((</span><span class="n">d2</span><span class="o">-</span><span class="n">d1</span><span class="p">)</span><span class="o">*</span><span class="mi">1000</span><span class="p">))</span>
</code></pre></div></div>

<p>Finally, let’s take a look at the emulation function. This function follows the following process:</p>

<ol>
  <li>It reads the opcodes from the memory pointed to by the current <code class="language-plaintext highlighter-rouge">program counter</code> register.</li>
  <li>It disassembles the instruction.</li>
  <li>It tells Triton to apply the semantics of the instruction by calling its <code class="language-plaintext highlighter-rouge">processing</code> function.</li>
  <li>It advances the pointer to the next instruction.</li>
</ol>

<p>Here is the code for the emulation function:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">emulate</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">pc</span><span class="p">):</span>
    <span class="c1"># emulation loop
</span>    <span class="k">while</span> <span class="n">pc</span><span class="p">:</span>
        <span class="n">opcodes</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
        <span class="n">instruction</span> <span class="o">=</span> <span class="n">Instruction</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="n">opcodes</span><span class="p">)</span>

        <span class="s">'''
        You can insert some logic here
        '''</span>

        <span class="c1"># process the instruction
</span>        <span class="n">ret</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">processing</span><span class="p">(</span><span class="n">instruction</span><span class="p">)</span>
        <span class="c1"># if HALT, finish the execution
</span>        <span class="k">if</span> <span class="n">instruction</span><span class="p">.</span><span class="n">getType</span><span class="p">()</span> <span class="o">==</span> <span class="n">OPCODE</span><span class="p">.</span><span class="n">X86</span><span class="p">.</span><span class="n">HLT</span><span class="p">:</span>
            <span class="k">break</span>
        <span class="c1"># apply one of the handlers that are not provided by
</span>        <span class="c1"># Triton
</span>        <span class="n">hookingHandler</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
        <span class="c1"># Next
</span>        <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
</code></pre></div></div>

<p>Previous code represents a common emulation function for Triton, this body of function can be used almost in any analysis. Before moving to the next instruction we called <code class="language-plaintext highlighter-rouge">hookingHandler</code>, a function that will call our own hooks. I left a comment where we can insert some logic of analysis, apply symbolization of registers or memory, apply constraints and finally solve the expressions for getting a model.</p>

<h3 id="apply-constraints">Apply Constraints</h3>

<p>Before I didn’t paste the whole code for <code class="language-plaintext highlighter-rouge">emulate</code> function, but I will paste here and I will give some explanations more:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">emulate</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">pc</span><span class="p">):</span>

    <span class="n">check_register_value</span> <span class="o">=</span> <span class="p">[</span>
        <span class="p">[</span><span class="n">FIRST_CONDITIONAL</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">eax</span><span class="p">,</span> <span class="mh">0x1cd4</span><span class="p">],</span> <span class="c1"># 0x000012bf
</span>        <span class="p">[</span><span class="n">SECOND_CONDITIONAL</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">eax</span><span class="p">,</span> <span class="mh">0xd899</span><span class="p">],</span> <span class="c1"># 0x000012e0
</span>        <span class="p">[</span><span class="n">THIRD_CONDITIONAL</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rdx</span><span class="p">,</span> <span class="mh">0xa04233a475d1b72</span><span class="p">],</span> <span class="c1"># 0x000013c5
</span>        <span class="p">[</span><span class="n">FOURTH_CONDITIONAL</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">eax</span><span class="p">,</span> <span class="mh">0x4b5469c</span><span class="p">],</span> <span class="c1"># 0x00001447
</span>        <span class="p">[</span><span class="n">FIFTH_CONDITIONAL</span><span class="p">,</span> <span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">r8</span><span class="p">,</span> <span class="mh">0x231f0b21595d0455</span><span class="p">]</span> <span class="c1"># 0x00001492
</span>    <span class="p">]</span>

    <span class="n">loop_address_dest</span> <span class="o">=</span> <span class="p">[</span>
        <span class="p">[</span><span class="n">FIRST_LOOP</span><span class="p">,</span> <span class="mh">0x0000141d</span><span class="p">],</span>
        <span class="p">[</span><span class="n">SECOND_LOOP</span><span class="p">,</span> <span class="mh">0x00001483</span><span class="p">]</span>
    <span class="p">]</span>

    <span class="c1"># emulation loop
</span>    <span class="k">while</span> <span class="n">pc</span><span class="p">:</span>

        <span class="c1">#print("[-] Running instruction at address: 0x%08X" % (pc))
</span>        <span class="n">opcodes</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
        <span class="n">instruction</span> <span class="o">=</span> <span class="n">Instruction</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="n">opcodes</span><span class="p">)</span>

        <span class="c1"># call a not implemented function, jump over it
</span>        <span class="c1"># adding the length of a call instruction
</span>        <span class="k">if</span> <span class="n">pc</span> <span class="ow">in</span> <span class="p">[</span><span class="mh">0x0000124a</span><span class="p">,</span> <span class="mh">0x00001254</span><span class="p">,</span> <span class="mh">0x0000126d</span><span class="p">]:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"Not emulated function, continue"</span><span class="p">)</span>
            <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
            <span class="n">pc</span> <span class="o">+=</span> <span class="mi">5</span>
            <span class="k">continue</span>
        <span class="c1"># avoid decryption loops
</span>        <span class="n">avoid_loop</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">loop_address_dest</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">"Decryption loop address 0x%08X, moving to 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
                <span class="n">pc</span> <span class="o">=</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
                <span class="n">avoid_loop</span> <span class="o">=</span> <span class="bp">True</span>
                <span class="k">break</span>

        <span class="k">if</span> <span class="n">avoid_loop</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="c1"># conditions
</span>        <span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">check_register_value</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">"Checking at address: 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
                <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">FIFTH_CONDITIONAL</span><span class="p">:</span>
                    <span class="c1"># in this case provide True for solving the expression
</span>                    <span class="n">solver_check</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">val</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="bp">True</span><span class="p">)</span>
                    <span class="k">return</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">solver_check</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">val</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>

        <span class="c1"># process the instruction
</span>        <span class="n">ret</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">processing</span><span class="p">(</span><span class="n">instruction</span><span class="p">)</span>
        <span class="c1"># if HALT, finish the execution
</span>        <span class="k">if</span> <span class="n">instruction</span><span class="p">.</span><span class="n">getType</span><span class="p">()</span> <span class="o">==</span> <span class="n">OPCODE</span><span class="p">.</span><span class="n">X86</span><span class="p">.</span><span class="n">HLT</span><span class="p">:</span>
            <span class="k">break</span>
        <span class="c1"># apply one of the handlers that are not provided by
</span>        <span class="c1"># Triton
</span>        <span class="n">hookingHandler</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>

        <span class="c1"># Next
</span>        <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
</code></pre></div></div>

<p>First of all, as I said during the analysis of the binary, we will avoid two different codes, functions that are not implemented, and are not important for the analysis, we annotated the addresses of the calls, and we skipped them with the next code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># call a not implemented function, jump over it
# adding the length of a call instruction
</span><span class="k">if</span> <span class="n">pc</span> <span class="ow">in</span> <span class="p">[</span><span class="mh">0x0000124a</span><span class="p">,</span> <span class="mh">0x00001254</span><span class="p">,</span> <span class="mh">0x0000126d</span><span class="p">]:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Not emulated function, continue"</span><span class="p">)</span>
    <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
    <span class="n">pc</span> <span class="o">+=</span> <span class="mi">5</span>
    <span class="k">continue</span>
</code></pre></div></div>

<p>Finally, let’s discuss another important part: the decryption loops. As mentioned before, we can actually avoid these decryption loops since they are not crucial for the analysis. Skipping them will help save time and memory during the symbolic execution.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># avoid decryption loops
</span><span class="n">avoid_loop</span> <span class="o">=</span> <span class="bp">False</span>
<span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">loop_address_dest</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"Decryption loop address 0x%08X, moving to 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
        <span class="n">pc</span> <span class="o">=</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="n">avoid_loop</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="k">break</span>

<span class="k">if</span> <span class="n">avoid_loop</span><span class="p">:</span>
    <span class="k">continue</span>
</code></pre></div></div>

<p>For finishing explaining the code, we have the next snippet:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># conditions
</span><span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">check_register_value</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"Checking at address: 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
        <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">FIFTH_CONDITIONAL</span><span class="p">:</span>
            <span class="c1"># in this case provide True for solving the expression
</span>            <span class="n">solver_check</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">val</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="bp">True</span><span class="p">)</span>
            <span class="k">return</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">solver_check</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">val</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">val</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
</code></pre></div></div>

<p>This code will check the address, and it will call <code class="language-plaintext highlighter-rouge">solver_check</code>, in this function we will apply the constraints, the second parameter of the function is a register and the third parameter a value, both used for applying a constraint:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">solver_check</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">register</span><span class="p">,</span> <span class="n">CHECK_VALUE</span><span class="p">,</span> <span class="n">solve</span> <span class="o">=</span> <span class="bp">False</span><span class="p">,</span> <span class="n">show_ast</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
    <span class="c1"># get the register AST
</span>    <span class="n">reg</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getRegisterAst</span><span class="p">(</span><span class="n">register</span><span class="p">)</span>
    
    <span class="c1"># add the constraint
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">pushPathConstraint</span><span class="p">(</span><span class="n">reg</span> <span class="o">==</span> <span class="n">CHECK_VALUE</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">show_ast</span><span class="p">:</span>
        <span class="c1"># in case user wants, show the AST of the expression
</span>        <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
        <span class="n">reg_ast</span> <span class="o">=</span> <span class="n">ast</span><span class="p">.</span><span class="n">unroll</span><span class="p">(</span><span class="n">reg</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="n">reg_ast</span><span class="p">)</span>

    <span class="p">...</span>

    <span class="c1"># to meet the comparison, set the value of the register
</span>    <span class="c1"># to the value checked.
</span>    <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteRegisterValue</span><span class="p">(</span><span class="n">register</span><span class="p">,</span> <span class="n">CHECK_VALUE</span><span class="p">)</span>
</code></pre></div></div>

<p>The previous code will apply the different constraints once the execution reach the different comparisons, and finally it will set the constant value into the register used in the comparison to keep running properly.</p>

<h3 id="solve-the-final-expression-with-the-constraints">Solve the final expression with the constraints</h3>

<p>We are almost done with Triton. In the <code class="language-plaintext highlighter-rouge">solver_check</code> function, I didn’t past some code that will execute if the <code class="language-plaintext highlighter-rouge">solve</code> parameter is set to <code class="language-plaintext highlighter-rouge">True</code>. This part of the code applies a final constraint, retrieves the expression from the Abstract Syntax Tree (AST), attempts to solve it using Z3, and obtains a model if successful.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">solve</span><span class="p">):</span>
    <span class="c1"># solve and retrieve the flag
</span>    <span class="n">cstr</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getPathPredicate</span><span class="p">()</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getModel</span><span class="p">(</span><span class="n">cstr</span><span class="p">)</span>
    <span class="n">key_values</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">m</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
        <span class="n">key_values</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>
    
    <span class="n">flag</span> <span class="o">=</span> <span class="s">""</span>
    <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">key_values</span><span class="p">.</span><span class="n">keys</span><span class="p">()):</span>
        <span class="n">v</span> <span class="o">=</span> <span class="n">key_values</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
        <span class="n">symbar</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicVariable</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
        <span class="c1">#print(f"{symbar} ({k}) = {hex(v.getValue())} ({chr(v.getValue())})")
</span>        <span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">getValue</span><span class="p">())</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n\n</span><span class="s">------------------------------------------"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Flag=</span><span class="si">{</span><span class="n">flag</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"------------------------------------------</span><span class="se">\n\n</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>

<p>Using the previous code, we obtain the expression and attempt to obtain a model that satisfies the constraints. If we successfully obtain a model, we can retrieve the values for each variable in the solution. The obtained values may look something like this:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>python3 triton_solver.py
<span class="c">...
</span><span class="go">flag_0:8 (0) = 0x46 (F)
flag_1:8 (1) = 0x72 (r)
flag_2:8 (2) = 0x33 (3)
flag_3:8 (3) = 0x33 (3)
flag_4:8 (4) = 0x5f (_)
flag_5:8 (5) = 0x4d (M)
flag_6:8 (6) = 0x34 (4)
flag_7:8 (7) = 0x64 (d)
flag_8:8 (8) = 0x61 (a)
flag_9:8 (9) = 0x6d (m)
flag_10:8 (10) = 0x33 (3)
flag_11:8 (11) = 0x2d (-)
flag_12:8 (12) = 0x44 (D)
flag_13:8 (13) = 0x65 (e)
flag_14:8 (14) = 0x2f (/)
flag_15:8 (15) = 0x4d (M)
flag_16:8 (16) = 0x34 (4)
flag_17:8 (17) = 0x69 (i)
flag_18:8 (18) = 0x6e (n)
flag_19:8 (19) = 0x74 (t)
flag_20:8 (20) = 0x65 (e)
flag_21:8 (21) = 0x6e (n)
flag_22:8 (22) = 0x30 (0)
flag_23:8 (23) = 0x6e (n)
</span></code></pre></div></div>

<p>But let’s printing it as a string, and will show it in a nice way :D</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>python3 triton_solver.py 
<span class="go">[+] Loading 0x000040 - 0x000318
[+] Loading 0x000318 - 0x000334
[+] Loading 0x000000 - 0x000a88
[+] Loading 0x001000 - 0x001d11
[+] Loading 0x002000 - 0x0021d0
[+] Loading 0x003d28 - 0x15df4c
[+] Loading 0x003d38 - 0x003f48
[+] Loading 0x000338 - 0x000368
[+] Loading 0x000368 - 0x0003ac
[+] Loading 0x000338 - 0x000368
[+] Loading 0x002038 - 0x002084
[+] Loading 0x000000 - 0x000000
[+] Loading 0x003d28 - 0x004000
[+] Applying relocations and extracting the addresses for the external functions
[+] Init PLT for: strncpy
[+] Init PLT for: __libc_start_main
[+] Starting emulation from entry point 0x00001500
[+] __libc_start_main hooked
[+] argv[0] = b'./challenge'
[+] argv[1] = b'AAAAAAAAAAAAAAAAAAAAAAAA\x00'
Not emulated function, continue
Not emulated function, continue
Not emulated function, continue
[+] strncpy hooked
Symbolizing the user input in the address 0x9FFFFF80
Checking at address: 0x000012BF
Checking at address: 0x000012E0
Checking at address: 0x000013C5
Decryption loop address 0x000013CE, moving to 0x0000141D
Checking at address: 0x00001447
Decryption loop address 0x00001452, moving to 0x00001483
Checking at address: 0x00001492


------------------------------------------
Flag=Fr33_M4dam3-De/M4inten0n
------------------------------------------
</span></code></pre></div></div>

<p>Finally we obtain a password: <em>Fr33_M4dam3-De/M4inten0n</em>. Now let’s try running it as parameter for our challenge:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/26.png"><img src="/assets/images/hex-ray-challenge/26.png" /></a>
<figcaption>Solution for the challenge.</figcaption>
</figure>

<h2 id="solving-the-challenge-with-tritondse">Solving the Challenge With TritonDSE</h2>

<p>TritonDSE is a library built on top of Triton. It provides higher-level program exploration and analysis primitives, as stated in the Quarkslab post. It offers a <code class="language-plaintext highlighter-rouge">callback manager</code> that allows for the implementation of different hooking methods. TritonDSE includes a SymbolicExplorator that performs path exploration by generating new values to traverse the various branches of the code. Another advantage is that TritonDSE automatically loads the binary itself and already implements some API functions from <code class="language-plaintext highlighter-rouge">libc</code>, making the work of analysts easier.</p>

<p>Although the library was recently released and may still have some issues, it shows great promise for binary analysis. Unfortunately, due to time constraints, I wasn’t able to fully utilize TritonDSE for the challenge. Nonetheless, I will present my solution using TritonDSE and plan to enhance the script in the future as I learn more about it, aiming to solve the challenge in a more automated manner. For now, I will provide a simplified explanation in three steps:</p>

<ol>
  <li>Load the binary (create initial values, set callbacks, and run the executor).</li>
  <li>Skip non-emulated functions and loops, and set byte constraints.</li>
  <li>Set constraints and solve the challenge.</li>
</ol>

<h3 id="load-binary-configure-starting-values-configure-callbacks-and-run">Load Binary, configure starting values, configure callbacks and Run!</h3>

<p>The process of loading the binary and configuring values or callbacks becomes much easier with TritonDSE as it abstracts many of the internal details of Triton. We load the binary by calling the <code class="language-plaintext highlighter-rouge">Program</code> function and providing the file path as an argument. Then, we can generate the program arguments as a <code class="language-plaintext highlighter-rouge">Seed</code> object, which will later be passed as a parameter to the <code class="language-plaintext highlighter-rouge">SymbolicExecutor</code>. The <code class="language-plaintext highlighter-rouge">SymbolicExecutor</code> object will load the <code class="language-plaintext highlighter-rouge">Program</code> object and also contains a <code class="language-plaintext highlighter-rouge">callback_manager</code> where we can register different callbacks. I recommend referring to the documentation to understand all the available callbacks. In my case, I only used one callback before each run instruction and one callback after running each instruction. Here is the <code class="language-plaintext highlighter-rouge">main</code> function from my script:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="k">global</span> <span class="n">p</span>

    <span class="c1"># load the target into the engine
</span>    <span class="n">p</span> <span class="o">=</span> <span class="n">Program</span><span class="p">(</span><span class="n">TARGET</span><span class="p">)</span>

    <span class="c1"># now generate the first seed values
</span>    <span class="n">config</span> <span class="o">=</span> <span class="n">Config</span><span class="p">(</span><span class="n">coverage_strategy</span><span class="o">=</span><span class="n">CoverageStrategy</span><span class="p">.</span><span class="n">PATH</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
                <span class="n">pipe_stdout</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">seed_format</span><span class="o">=</span><span class="n">SeedFormat</span><span class="p">.</span><span class="n">COMPOSITE</span><span class="p">)</span>
    <span class="n">seed</span> <span class="o">=</span> <span class="n">Seed</span><span class="p">(</span><span class="n">CompositeData</span><span class="p">(</span><span class="n">argv</span><span class="o">=</span><span class="p">[</span><span class="sa">b</span><span class="s">"./challenge"</span><span class="p">,</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mh">0x18</span><span class="p">]))</span>

    <span class="c1"># create a symbolic explorator to go
</span>    <span class="c1"># symbolically over the program
</span>    <span class="n">executor</span> <span class="o">=</span> <span class="n">SymbolicExecutor</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">seed</span><span class="p">)</span>
    <span class="n">executor</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
    
    <span class="c1"># set the callbacks for pre and post instruction
</span>    <span class="n">executor</span><span class="p">.</span><span class="n">callback_manager</span><span class="p">.</span><span class="n">register_pre_instruction_callback</span><span class="p">(</span><span class="n">trace_inst</span><span class="p">)</span>
    <span class="n">executor</span><span class="p">.</span><span class="n">callback_manager</span><span class="p">.</span><span class="n">register_post_instruction_callback</span><span class="p">(</span><span class="n">skip</span><span class="p">)</span>

    <span class="n">executor</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
</code></pre></div></div>

<p>As you can see, the code is pretty straightforward, which is nice from an analysis perspective. We don’t need to write many lines of code to load a program and apply relocations, etc.</p>

<h3 id="skip-not-emulated-functions-loops-and-set-bytes-constraints">Skip not emulated functions, loops and set bytes constraints</h3>

<p>I’ve found that if I try to skip a function in a <em>pre</em> callback, or in the hook of an <code class="language-plaintext highlighter-rouge">API</code> call, the program crashed or it didn’t work. In the case of the <code class="language-plaintext highlighter-rouge">API</code> calls, it crashes because the <code class="language-plaintext highlighter-rouge">__default_stub</code> function is called when a call to a not supported <code class="language-plaintext highlighter-rouge">API</code> is run, and the program tries to obtain an address using the <code class="language-plaintext highlighter-rouge">program_counter</code>, you can find the code <a href="https://github.com/quarkslab/tritondse/blob/main/tritondse/symbolic_executor.py#L496C9-L496C16">here</a>. But because in the hook of the <code class="language-plaintext highlighter-rouge">API</code> I modify the <code class="language-plaintext highlighter-rouge">RIP</code> register, the value accessed in Python’s map doesn’t exist and program crashes.</p>

<p>In my implementation, similar to how I handled Triton’s code, I have a mechanism to skip functions. I wait for the execution of the <code class="language-plaintext highlighter-rouge">call</code> instruction and then retrieve the return address stored in the <code class="language-plaintext highlighter-rouge">RIP</code> register. I also adjust the stack pointer <code class="language-plaintext highlighter-rouge">RSP</code> to clean up the stack. As for the decryption loops, I simply modify the <code class="language-plaintext highlighter-rouge">RIP</code> register and set it to the address following the decryption loop. After the <code class="language-plaintext highlighter-rouge">strncpy</code> call is completed, I apply ASCII constraints to each byte of the <code class="language-plaintext highlighter-rouge">argv[1]</code> value. The memory address of <code class="language-plaintext highlighter-rouge">argv[1]</code> is stored in the variable <code class="language-plaintext highlighter-rouge">MEM_ADDRESS</code>, and I will explain where this variable is written in the next section.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">skip</span><span class="p">(</span><span class="n">se</span><span class="p">:</span> <span class="n">SymbolicExecutor</span><span class="p">,</span> <span class="n">pstate</span><span class="p">:</span> <span class="n">ProcessState</span><span class="p">,</span> <span class="n">inst</span><span class="p">:</span> <span class="n">Instruction</span><span class="p">):</span>
    <span class="n">pc</span> <span class="o">=</span> <span class="n">inst</span><span class="p">.</span><span class="n">getAddress</span><span class="p">()</span>
    <span class="k">if</span> <span class="n">pc</span> <span class="ow">in</span> <span class="p">[</span><span class="mh">0x0000124a</span><span class="p">,</span> <span class="mh">0x00001254</span><span class="p">,</span> <span class="mh">0x0000126d</span><span class="p">]:</span> <span class="c1"># useless calls
</span>        <span class="k">print</span><span class="p">(</span><span class="s">"[+] Not emulated function, continue"</span><span class="p">)</span>
        <span class="c1"># restore rip to a correct one
</span>        <span class="n">pstate</span><span class="p">.</span><span class="n">write_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">,</span> <span class="n">pc</span> <span class="o">+</span> <span class="n">inst</span><span class="p">.</span><span class="n">getSize</span><span class="p">())</span>
        <span class="c1"># fix rsp
</span>        <span class="n">rsp</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">)</span>
        <span class="n">pstate</span><span class="p">.</span><span class="n">write_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsp</span><span class="p">,</span> <span class="n">rsp</span><span class="o">+</span><span class="mi">8</span><span class="p">)</span>
        <span class="k">return</span>
    
    <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="mh">0x000012a0</span><span class="p">:</span> <span class="c1"># post strncpy
</span>        <span class="n">valid_characters</span> <span class="o">=</span> <span class="s">"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!</span><span class="se">\"</span><span class="s">#$%&amp;</span><span class="se">\'</span><span class="s">()*+,-./:;&lt;=&gt;?@[</span><span class="se">\\</span><span class="s">]^_`{|}~"</span>
        <span class="n">min_value</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">valid_characters</span><span class="p">))</span>
        <span class="n">max_value</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">valid_characters</span><span class="p">))</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[+] strncpy adding constraints to symbolized memory"</span><span class="p">)</span>
        <span class="c1"># apply the constraint to the AST of each byte
</span>        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mh">0x18</span><span class="p">):</span>
            <span class="n">sym_mem</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_symbolic_memory_byte</span><span class="p">(</span><span class="n">MEM_ADDRESS</span><span class="o">+</span><span class="n">i</span><span class="p">)</span>
            <span class="n">pstate</span><span class="p">.</span><span class="n">push_constraint</span><span class="p">(</span><span class="n">sym_mem</span><span class="p">.</span><span class="n">getAst</span><span class="p">()</span> <span class="o">&gt;=</span> <span class="n">min_value</span><span class="p">)</span>
            <span class="n">pstate</span><span class="p">.</span><span class="n">push_constraint</span><span class="p">(</span><span class="n">sym_mem</span><span class="p">.</span><span class="n">getAst</span><span class="p">()</span> <span class="o">&lt;=</span> <span class="n">max_value</span><span class="p">)</span>
    
    <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">loop_address_dest</span><span class="p">:</span> <span class="c1"># for stepping out the loops
</span>        <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"[+] Found call to decryption loop, skipping"</span><span class="p">)</span>
            <span class="n">pstate</span><span class="p">.</span><span class="n">write_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">,</span> <span class="n">value</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
            <span class="k">return</span>
</code></pre></div></div>

<h3 id="set-constraints-and-solve-the-challenge">Set constraints and solve the challenge.</h3>

<p>Finally, we have the callback that runs before each instruction. In this callback, I push various constraints into the expressions. Once we reach the final comparison, I push the last constraint and solve the challenge by searching for a model that satisfies all the expressions. As mentioned earlier, I also store the address of <code class="language-plaintext highlighter-rouge">argv[1]</code> in the <code class="language-plaintext highlighter-rouge">MEM_ADDRESS</code> variable. This is done during the <code class="language-plaintext highlighter-rouge">strncpy</code> call, where the address is one of the parameters.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">trace_inst</span><span class="p">(</span><span class="n">se</span><span class="p">:</span> <span class="n">SymbolicExecutor</span><span class="p">,</span> <span class="n">pstate</span><span class="p">:</span> <span class="n">ProcessState</span><span class="p">,</span> <span class="n">inst</span><span class="p">:</span> <span class="n">Instruction</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">MEM_ADDRESS</span>

    <span class="n">pc</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
    
    <span class="p">...</span>

    <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="mh">0x000012a0</span><span class="p">:</span> <span class="c1"># call to strncpy
</span>        <span class="n">rsi</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rsi</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[+] Strncpy getting source value: 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">rsi</span><span class="p">))</span>
        <span class="c1"># save address of argv
</span>        <span class="n">MEM_ADDRESS</span> <span class="o">=</span> <span class="n">rsi</span>
    
    <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">check_register_value</span><span class="p">:</span>
        <span class="c1"># go over the jumps of each check
</span>        <span class="c1"># and apply the constraint with the used
</span>        <span class="c1"># register.
</span>        <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"[-] Found jump instruction, skipping it"</span><span class="p">)</span>
            <span class="n">sym_reg</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_symbolic_register</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
            <span class="n">pstate</span><span class="p">.</span><span class="n">push_constraint</span><span class="p">(</span><span class="n">sym_reg</span><span class="p">.</span><span class="n">getAst</span><span class="p">()</span> <span class="o">==</span> <span class="n">value</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
            <span class="c1"># to make sure the comparison always match
</span>            <span class="n">pstate</span><span class="p">.</span><span class="n">write_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">zf</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="c1"># Last constraint and solution of the system
</span>    <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="n">FIFTH_CONDITIONAL</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[!] Got final instruction!"</span><span class="p">)</span>
        <span class="n">sym_r8</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_symbolic_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">r8</span><span class="p">)</span>
        <span class="n">sym_rax</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_symbolic_register</span><span class="p">(</span><span class="n">pstate</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rax</span><span class="p">)</span>
        <span class="n">status</span><span class="p">,</span> <span class="n">model</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">solve</span><span class="p">(</span><span class="n">sym_r8</span><span class="p">.</span><span class="n">getAst</span><span class="p">()</span> <span class="o">==</span> <span class="n">sym_rax</span><span class="p">.</span><span class="n">getAst</span><span class="p">())</span>

        <span class="c1"># If formula is SAT retrieve input values
</span>        <span class="k">if</span> <span class="n">status</span> <span class="o">==</span> <span class="n">SolverStatus</span><span class="p">.</span><span class="n">SAT</span><span class="p">:</span>
            <span class="c1"># Retrieve value of the input variable involved in the cl value here (shall be only one here)
</span>            <span class="n">sym_mem</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">read_symbolic_memory_bytes</span><span class="p">(</span><span class="n">MEM_ADDRESS</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)</span>
            <span class="n">var_values</span> <span class="o">=</span> <span class="n">pstate</span><span class="p">.</span><span class="n">get_expression_variable_values_model</span><span class="p">(</span><span class="n">sym_mem</span><span class="p">,</span> <span class="n">model</span><span class="p">)</span>
            <span class="n">key_values</span> <span class="o">=</span> <span class="p">{}</span>
            <span class="k">for</span> <span class="n">var</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">var_values</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
                <span class="n">key_values</span><span class="p">[</span><span class="n">var</span><span class="p">.</span><span class="n">getId</span><span class="p">()]</span> <span class="o">=</span> <span class="n">value</span>
            
            <span class="n">flag</span> <span class="o">=</span> <span class="s">""</span>
            <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">key_values</span><span class="p">.</span><span class="n">keys</span><span class="p">()):</span>
                <span class="n">v</span> <span class="o">=</span> <span class="n">key_values</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
                <span class="n">flag</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n\n</span><span class="s">------------------------------------------"</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Flag=</span><span class="si">{</span><span class="n">flag</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"------------------------------------------</span><span class="se">\n\n</span><span class="s">"</span><span class="p">)</span>
            <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">print</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
</code></pre></div></div>

<p>The structure <code class="language-plaintext highlighter-rouge">check_register_value</code> is pretty similar to the one shown in Triton’s part, and the code is similar too. In case the program counter value is one from <code class="language-plaintext highlighter-rouge">check_register_value</code>, we push a new constraint where the given register must be the same to the provided value, then we set <code class="language-plaintext highlighter-rouge">ZF</code> (zero flag) to 1, so the comparison will be true. Finally, if the address is the last condition, we push a final constraint and solve the expression as I did before.</p>

<p>If we run the script, we will get the next output:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/27.png"><img src="/assets/images/hex-ray-challenge/27.png" /></a>
<figcaption>Running TritonDSE script and getting the password.</figcaption>
</figure>

<p>As we can see, the output is similar to the previous one from Triton’s script but with some logging code. Again we obtain the correct password, and running the challenge with the password will give us the same result. So with this we have finished with the part of TritonDSE!!!</p>

<p>You can find the full script for this challenge in <a href="https://github.com/Fare9/My-Symbolic-Execution/blob/master/IDA-challenge/free-madame-de-maintenon-challenge/tritondse_solver.py">here</a>.</p>

<h2 id="using-z3-together-with-triton">Using Z3 Together with Triton</h2>

<p>This part will conclude the solution of the challenge, as a way to start learning about Triton. In this part of the post, I will use an external tool for solving the challenge, the script this time will directly use Z3, instead of calling it through Triton. The idea for this, as well as most of the code comes from the solution for <em>HackCon2016</em> in Triton’s repository: <a href="https://github.com/JonathanSalwan/Triton/blob/master/src/examples/python/ctf-writeups/hackcon-2016-angry-reverser/solve.py">script</a>.</p>

<p>Internally Triton will use Z3 or Bitwuzla for solving the expressions, but you can directly use a tool like Z3 as a python library in the script. For using Z3 we need to prepare an expression in SMT format that Z3 can parse, and for doing that we will have two auxiliary functions:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">getVarSyntax</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
    <span class="n">s</span> <span class="o">=</span> <span class="nb">str</span><span class="p">()</span>
    <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicVariables</span><span class="p">().</span><span class="n">items</span><span class="p">()):</span>
        <span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">ast</span><span class="p">.</span><span class="n">declare</span><span class="p">(</span><span class="n">ast</span><span class="p">.</span><span class="n">variable</span><span class="p">(</span><span class="n">v</span><span class="p">)))</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
    <span class="k">return</span> <span class="n">s</span>

<span class="k">def</span> <span class="nf">getSSA</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">expr</span><span class="p">):</span>
    <span class="n">s</span> <span class="o">=</span> <span class="nb">str</span><span class="p">()</span>
    <span class="c1"># current AST of the program
</span>    <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
    <span class="c1"># generate an IR in SSA from the expression
</span>    <span class="n">ssa</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">sliceExpressions</span><span class="p">(</span><span class="n">expr</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">ssa</span><span class="p">.</span><span class="n">items</span><span class="p">())[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
        <span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
    <span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">ast</span><span class="p">.</span><span class="n">assert_</span><span class="p">(</span><span class="n">expr</span><span class="p">.</span><span class="n">getAst</span><span class="p">()))</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
    <span class="k">return</span> <span class="n">s</span>
</code></pre></div></div>

<p>In previous snippet we have two functions, <code class="language-plaintext highlighter-rouge">getVarSyntax</code> will generate all the variables for Z3 based on the symbolic variables from Triton, the output from the function is an string where each line has the next format:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(declare-fun &lt;symbolic_var_N&gt; () (_ BitVec &lt;size in bits&gt;))
</code></pre></div></div>

<p>The other function <code class="language-plaintext highlighter-rouge">getSSA</code>, will get the expression given as parameter, but this time in SMT format with Static Single-Assignment (SSA), this kind of representation is used in compilers’ IRs, where each variable is just assigned once. The format of the output is the next one:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(define-fun ref!269 () (_ BitVec 8) SymVar_8) ; Byte reference
(define-fun ref!271 () (_ BitVec 8) SymVar_9) ; Byte reference
(define-fun ref!281 () (_ BitVec 8) SymVar_14) ; Byte reference
(define-fun ref!283 () (_ BitVec 8) SymVar_15) ; Byte reference
(define-fun ref!285 () (_ BitVec 8) SymVar_16) ; Byte reference
(define-fun ref!287 () (_ BitVec 8) SymVar_17) ; Byte reference
(define-fun ref!297 () (_ BitVec 8) SymVar_22) ; Byte reference
(define-fun ref!299 () (_ BitVec 8) SymVar_23) ; Byte reference
(define-fun ref!300 () (_ BitVec 16) (concat ref!287 ref!285)) ; Extended part - Extended part - MOVZX operation
(define-fun ref!301 () (_ BitVec 32) ((_ zero_extend 16) ref!300)) ; Extended part - MOVZX operation
(define-fun ref!304 () (_ BitVec 16) (concat ref!299 ref!297)) ; Extended part - Extended part - MOVZX operation
(define-fun ref!305 () (_ BitVec 32) ((_ zero_extend 16) ref!304)) ; Extended part - MOVZX operation
(define-fun ref!308 () (_ BitVec 32) (bvadd ref!305 ref!301)) ; Extended part - ADD operation
(define-fun ref!317 () (_ BitVec 16) (concat ref!271 ref!269)) ; Extended part - Extended part - MOVZX operation
(define-fun ref!318 () (_ BitVec 32) ((_ zero_extend 16) ref!317)) ; Extended part - MOVZX operation
(define-fun ref!321 () (_ BitVec 32) (bvsub ref!308 ref!318)) ; Extended part - SUB operation
(define-fun ref!330 () (_ BitVec 16) (concat ref!283 ref!281)) ; Extended part - Extended part - MOVZX operation
(define-fun ref!331 () (_ BitVec 32) ((_ zero_extend 16) ref!330)) ; Extended part - MOVZX operation
(define-fun ref!334 () (_ BitVec 32) (bvsub ref!321 ref!331)) ; Extended part - SUB operation
(define-fun ref!343 () (_ BitVec 32) (bvsub ref!334 (_ bv7380 32))) ; CMP operation
(assert (= (ite (= ref!343 (_ bv0 32)) (_ bv1 1) (_ bv0 1)) (_ bv1 1)))
</code></pre></div></div>

<p>Now we can compare previous representation with the one from Triton, Triton represent the expression with an AST like the next:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(bvsub (bvsub (bvadd ((_ zero_extend 16) (concat flag_23 flag_22)) ((_ zero_extend 16) (concat flag_17 flag_16))) ((_ zero_extend 16) (concat flag_9 flag_8))) ((_ zero_extend 16) (concat flag_15 flag_14)))
</code></pre></div></div>

<p>While the input from Z3 can look longer, after talking with Jonathan Salwan (Main author from Triton), it looks like for long expressions Z3 parses faster the SMT expressions than Triton transforms from the AST to the expressions for Z3. So for some challenges where expressions are heavier to load, we can try using the method presented in this part of the post.</p>

<p>Now we need a function that interacts with Z3 library, this will create the symbolic expression to solve, and will generate the symbolic variables and the SSA form for Z3, find a solution for the expression, and in case some solution exists, return it for applying the concrete values to the symbolic variables:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">myExternalSolver</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">addr</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
    <span class="kn">import</span> <span class="nn">z3</span>
    <span class="n">expr</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">newSymbolicExpression</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="s">"Custom for Solver"</span><span class="p">)</span>
    <span class="n">varSyntax</span> <span class="o">=</span> <span class="n">getVarSyntax</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
    <span class="n">ssa</span> <span class="o">=</span> <span class="n">getSSA</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">expr</span><span class="p">)</span>

    <span class="n">smtFormat</span> <span class="o">=</span> <span class="s">'(set-logic QF_BV) %s %s (check-sat) (get-model)'</span> <span class="o">%</span> <span class="p">(</span>
        <span class="n">varSyntax</span><span class="p">,</span> <span class="n">ssa</span><span class="p">)</span>

    <span class="n">c</span> <span class="o">=</span> <span class="n">z3</span><span class="p">.</span><span class="n">Context</span><span class="p">()</span>
    <span class="n">s</span> <span class="o">=</span> <span class="n">z3</span><span class="p">.</span><span class="n">Solver</span><span class="p">(</span><span class="n">ctx</span><span class="o">=</span><span class="n">c</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">z3</span><span class="p">.</span><span class="n">parse_smt2_string</span><span class="p">(</span><span class="n">smtFormat</span><span class="p">,</span> <span class="n">ctx</span><span class="o">=</span><span class="n">c</span><span class="p">))</span>
    <span class="k">if</span> <span class="n">addr</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">'[+] Solving condition at %#x'</span> <span class="o">%</span> <span class="p">(</span><span class="n">addr</span><span class="p">))</span>
    <span class="k">if</span> <span class="n">s</span><span class="p">.</span><span class="n">check</span><span class="p">()</span> <span class="o">==</span> <span class="n">z3</span><span class="p">.</span><span class="n">sat</span><span class="p">:</span>
        <span class="n">ret</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
        <span class="n">model</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">model</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">model</span><span class="p">:</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="s">"ref"</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
                <span class="n">ret</span><span class="p">.</span><span class="n">update</span><span class="p">(</span>
                    <span class="p">{</span><span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">'_'</span><span class="p">)[</span><span class="mi">1</span><span class="p">],</span> <span class="mi">10</span><span class="p">):</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">model</span><span class="p">[</span><span class="n">x</span><span class="p">]),</span> <span class="mi">10</span><span class="p">)})</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">continue</span>
        <span class="k">return</span> <span class="n">ret</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">'[-] unsat :('</span><span class="p">)</span>
        <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span>
</code></pre></div></div>

<p>In the previous code snippet, we create a symbolic expression from one of the parameters, this expression will be used to generate the SSA form. Then a string is created with the symbolic variables and the SSA expressions. This string in SMT format will be the input for Z3, for doing that we call <code class="language-plaintext highlighter-rouge">parse_smt2_string</code>, that will parse the string, and will generate the necessary constraints and expressions for Z3, and then we check if a solution can be found (comparison with <code class="language-plaintext highlighter-rouge">z3.sat</code>), in case a solution is found, we will retrieve the model that solves the system. I have found that sometimes the solution for the system includes the <code class="language-plaintext highlighter-rouge">ref!...</code> used as reference of the operation or reference of a symbolic variable in Z3, and when parsing the output the function will crash, since we find concrete values for symbolic variables, we will just skip them. In case of a symbolic variable, we will retrieve the name of the symbolic variable and a concrete value that solves the model.</p>

<p>Now, since we modified the solver function, we need to modify also the emulation function. This time we will just use a list to keep the addresses of the comparisons, and we will apply the check after processing the instruction, not before. Then we have the next emulation code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">emulate</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">pc</span><span class="p">):</span>

    <span class="c1"># This structure will be used for applying the constraints in certain
</span>    <span class="c1"># addresses from the program, give a register to apply the constraint
</span>    <span class="c1"># and the value used during the comparison.
</span>    <span class="n">check_register_value</span> <span class="o">=</span> <span class="p">[</span>
        <span class="n">FIRST_CONDITIONAL</span><span class="p">,</span>
        <span class="n">SECOND_CONDITIONAL</span><span class="p">,</span>
        <span class="n">THIRD_CONDITIONAL</span><span class="p">,</span>
        <span class="n">FOURTH_CONDITIONAL</span><span class="p">,</span>
        <span class="n">FIFTH_CONDITIONAL</span><span class="p">,</span>
    <span class="p">]</span>

    <span class="c1"># Structure used to jump over the decryption loops which are
</span>    <span class="c1"># not useful for the analysis
</span>    <span class="n">loop_address_dest</span> <span class="o">=</span> <span class="p">[</span>
        <span class="p">[</span><span class="n">FIRST_LOOP</span><span class="p">,</span> <span class="mh">0x0000141d</span><span class="p">],</span>
        <span class="p">[</span><span class="n">SECOND_LOOP</span><span class="p">,</span> <span class="mh">0x00001483</span><span class="p">]</span>
    <span class="p">]</span>

    <span class="c1"># emulation loop
</span>    <span class="k">while</span> <span class="n">pc</span><span class="p">:</span>

        <span class="c1"># print("[-] Running instruction at address: 0x%08X" % (pc))
</span>        <span class="n">opcodes</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteMemoryAreaValue</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
        <span class="n">instruction</span> <span class="o">=</span> <span class="n">Instruction</span><span class="p">(</span><span class="n">pc</span><span class="p">,</span> <span class="n">opcodes</span><span class="p">)</span>
        
        <span class="c1"># Code for stepping out code that is not necessary
</span>        <span class="c1"># to be executed
</span>
        <span class="c1"># here avoid the loops and the functions that
</span>        <span class="c1"># are not implemented
</span>        <span class="p">...</span>

        <span class="c1"># process the instruction
</span>        <span class="n">ret</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">processing</span><span class="p">(</span><span class="n">instruction</span><span class="p">)</span>
        <span class="c1"># if HALT, finish the execution
</span>        <span class="k">if</span> <span class="n">instruction</span><span class="p">.</span><span class="n">getType</span><span class="p">()</span> <span class="o">==</span> <span class="n">OPCODE</span><span class="p">.</span><span class="n">X86</span><span class="p">.</span><span class="n">HLT</span><span class="p">:</span>
            <span class="k">break</span>

        <span class="c1"># conditions
</span>        <span class="k">if</span> <span class="n">pc</span> <span class="ow">in</span> <span class="n">check_register_value</span><span class="p">:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"Checking at address: 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">val</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
            <span class="n">zf</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicRegister</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">zf</span><span class="p">).</span><span class="n">getAst</span><span class="p">()</span>
            <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
            <span class="n">pco</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getPathPredicate</span><span class="p">()</span>
            <span class="n">model</span> <span class="o">=</span> <span class="n">myExternalSolver</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">zf</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">pc</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">model</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
                <span class="n">ctx</span><span class="p">.</span><span class="n">setConcreteVariableValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicVariable</span><span class="p">(</span><span class="n">k</span><span class="p">),</span> <span class="n">v</span><span class="p">)</span>

        <span class="c1"># solve the equation and retrieve the whole Password
</span>        <span class="k">if</span> <span class="n">pc</span> <span class="o">==</span> <span class="mh">0x0000149b</span><span class="p">:</span>
            <span class="c1"># in this case provide True for solving the expression
</span>            <span class="n">ast</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getAstContext</span><span class="p">()</span>
            <span class="n">pco</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getPathPredicate</span><span class="p">()</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"Checking final at address: 0x%08X"</span> <span class="o">%</span> <span class="p">(</span><span class="n">pc</span><span class="p">))</span>
            <span class="n">mod</span> <span class="o">=</span> <span class="n">myExternalSolver</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">ast</span><span class="p">.</span><span class="n">land</span><span class="p">(</span>
                <span class="p">[</span><span class="n">pco</span><span class="p">]</span> <span class="o">+</span>
                <span class="p">[</span><span class="n">ast</span><span class="p">.</span><span class="n">variable</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicVariable</span><span class="p">(</span><span class="n">x</span><span class="p">))</span> <span class="o">&gt;=</span> <span class="mh">0x20</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)]</span> <span class="o">+</span>
                <span class="p">[</span><span class="n">ast</span><span class="p">.</span><span class="n">variable</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicVariable</span><span class="p">(</span><span class="n">x</span><span class="p">))</span> <span class="o">&lt;=</span> <span class="mh">0x7e</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)]</span> <span class="o">+</span>
                <span class="p">[</span><span class="n">ast</span><span class="p">.</span><span class="n">variable</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">getSymbolicVariable</span><span class="p">(</span><span class="n">x</span><span class="p">))</span> <span class="o">!=</span>
                 <span class="mh">0x00</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)]</span>
            <span class="p">))</span>
            <span class="n">serial</span> <span class="o">=</span> <span class="nb">str</span><span class="p">()</span>
            <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">mod</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
                <span class="n">serial</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"PASSWORD = %s"</span> <span class="o">%</span> <span class="p">(</span><span class="n">serial</span><span class="p">))</span>
            <span class="k">return</span>

        <span class="c1"># apply one of the handlers that are not provided by
</span>        <span class="c1"># Triton
</span>        <span class="n">hookingHandler</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>

        <span class="c1"># Next
</span>        <span class="n">pc</span> <span class="o">=</span> <span class="n">ctx</span><span class="p">.</span><span class="n">getConcreteRegisterValue</span><span class="p">(</span><span class="n">ctx</span><span class="p">.</span><span class="n">registers</span><span class="p">.</span><span class="n">rip</span><span class="p">)</span>
</code></pre></div></div>

<p>If we find one of the addresses from the comparisons, we will call the external solver, giving as a symbolic expression the AST that is set in the <code class="language-plaintext highlighter-rouge">ZF</code> (zero flag) after the comparison, that must be equal to the value 1. This function will return symbolic variables and concrete values that solves the expression. We will apply them as concrete values. And we will continue the execution.
After that we have a comparison, that is already out of the different checks, it will be here we we will solve the final expression. In order to solve the final expression and obtain the correct values, we will retrieve as we did in the previous solution, the <code class="language-plaintext highlighter-rouge">PathPredicate</code>, and we will include also three constraints for our symbolic variables to be ASCII strings. Once we find a solution, this time we will obtain all the values for the symbolic variables. And with this, the correct password.</p>

<p>Next we can see the output with this script:</p>

<figure>
<a href="/assets/images/hex-ray-challenge/28.png"><img src="/assets/images/hex-ray-challenge/28.png" /></a>
<figcaption>Using Z3 as an external tool for solving the challenge.</figcaption>
</figure>

<p>You can find the whole script <a href="https://github.com/Fare9/My-Symbolic-Execution/blob/master/IDA-challenge/free-madame-de-maintenon-challenge/triton_solver_z3.py">here</a></p>

<h2 id="conclusions">Conclusions</h2>

<p>I have found the challenge interesting and at the end not so difficult. From a reverse engineering point of view the binary is not hard to analyze, but the problem would be looking for solutions manually, or using brute force, or using other tools manually (we can solve this challenge writing a script for Z3 but this would take longer).</p>

<p>Regarding Triton or TritonDSE, I have found that while in both cases the documentation is a little bit <em>“tough”</em> to follow, but with a few examples and reading at same time documentation and source code, you can quickly write scripts useful for doing challenges like this, or even more difficult ones.</p>

<p>Finally I hope you enjoyed reading this post, this time it was a long post, but I think it was needed for understanding the challenge, and the process for solving it.</p>

<p>I want to thank <a href="https://twitter.com/yates82">Yates82</a> for his video solving the challenge with Binary Ninja, this video gave me the idea for doing the challenge using the covered tools and write the post. Also I want to thank <a href="https://twitter.com/JonathanSalwan">JonathanSalwan</a>, the main author of Triton, I think this tool is very useful and it offers a very high performance. And finally thank <a href="https://twitter.com/RobinDavid1">RobinDavid1</a> and Christian Heitman, authors of TritonDSE, I think this will make Triton more accessible, and easy to use, which will probably make more people using it.</p>

<p>See you Space Cowboy!</p>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Symbolic Execution" /><category term="Triton" /><category term="Python" /><category term="C++" /><category term="ELF" /><category term="Linux" /><category term="Quarkslab" /><category term="Binary Analysis" /><summary type="html"><![CDATA[Triton is a library for doing Symbolic Execution, useful for doing common CTF challenges and analyzing obfuscations. TritonDSE is a library built on top of Triton which provides easy and customizable Dynamic Symbolic Execution Capabilities]]></summary></entry><entry><title type="html">Kunai, a library for analyzing Dalvik Executable Files</title><link href="https://fare9.github.io/android/analysis/kunai-lib/" rel="alternate" type="text/html" title="Kunai, a library for analyzing Dalvik Executable Files" /><published>2023-06-10T00:00:00+00:00</published><updated>2023-06-10T15:44:00+00:00</updated><id>https://fare9.github.io/android/analysis/kunai-lib</id><content type="html" xml:base="https://fare9.github.io/android/analysis/kunai-lib/"><![CDATA[<p>Kunai is a project started around 2021 as a side project during one of the author’s PhD, and it has been refactored a couple of times with improvements on its C++ code. As we learned more about C++, we improved the base code from the project. In this post we will see a couple of already written projects in order to see how to use the library, so this will be just the beginning of a series of post about Kunai.</p>

<h2 id="authors">Authors</h2>

<ul>
  <li>Angela Sun</li>
  <li>Eduardo Blazquez</li>
</ul>

<h2 id="kunais-structure">Kunai’s structure</h2>

<p>Right now Kunai’s code looks similar to the structure you find in a project like <em>LLVM</em>. This is how the root of the project looks:</p>

<figure>
<a href="/assets/images/kunai/project-root.png"><img src="/assets/images/kunai/project-root.png" /></a>
<figcaption>Root folder from Kunai's project.</figcaption>
</figure>

<p>In the root folder we can find projects that are compiled using Kunai’s library, that will cover the topic of this post (we’ll see more interesting things in the future):</p>

<ul>
  <li><em>header-parser</em>: A very simple header printer to show the capabilities of Kunai library as a Dalvik header parser.</li>
  <li><em>dalvik-disassembler</em>: A command line disassembler for dalvik that allows different output formats.</li>
</ul>

<p>These are simple projects to show the capabilities of Kunai, and also as code documentation for anyone who wants to start using the library to have some code for easy copy-pasting.</p>

<p>The main part of the project is stored under the folder <code class="language-plaintext highlighter-rouge">kunai-lib/</code>, here we can find the whole project of the library:</p>

<figure>
<a href="/assets/images/kunai/kunai-lib.png"><img src="/assets/images/kunai/kunai-lib.png" /></a>
<figcaption>Folder with the code from Kunai's library.</figcaption>
</figure>

<p>Here we find the next folders:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">include/Kunai/</code>: <code class="language-plaintext highlighter-rouge">.hpp</code> and <code class="language-plaintext highlighter-rouge">.def</code> files from the library, here you can find all the header files from the project, internally it has the same structure as the <code class="language-plaintext highlighter-rouge">.cpp</code> files. Many of the definitions were moved from <code class="language-plaintext highlighter-rouge">.hpp</code> files, to <code class="language-plaintext highlighter-rouge">.def</code> files, making easier to maintain and modify in case it’s needed.</li>
  <li><code class="language-plaintext highlighter-rouge">lib</code>: folder with all the code in <code class="language-plaintext highlighter-rouge">.cpp</code> files, the structure is the same than in the headers folder.</li>
  <li><code class="language-plaintext highlighter-rouge">test</code>: Java code with different tests for the library.</li>
  <li><code class="language-plaintext highlighter-rouge">unit-tests</code>: different unit tests used for testing different parts of the library.</li>
</ul>

<p>Kunai also offers an <em>intermediate representation</em> (IR) for allowing easy analysis of the code, an analyst can analyze smali code using the disassemblers from the library, or can use the IR offered by Kunai.</p>

<p>In previous version, the offered IR was written from scratch, but now the IR is written using <a href="https://mlir.llvm.org/">MLIR</a>, a framework from <em>LLVM</em> project that allows easyly writing of IRs, all the code for this IR can be found in the folder <code class="language-plaintext highlighter-rouge">MjolnIR/</code> inside <code class="language-plaintext highlighter-rouge">kunai-lib/</code>.</p>

<p>Next is a graphical representation from Kunai library, and more information about the IR can be found in the presentation from <a href="/assets/slides/EuroLLVM2023.pdf">EuroLLVM 2023</a>.</p>

<figure>
<a href="/assets/images/kunai/Kunai-arch.png"><img src="/assets/images/kunai/Kunai-arch.png" /></a>
<figcaption>Structure of Kunai Project.</figcaption>
</figure>

<h3 id="kunai-library">Kunai Library</h3>

<p>As said at the beginning of the post, Kunai is intended to the analysis of Dalvik Executable Files, previous version also supported loading <code class="language-plaintext highlighter-rouge">apk</code> files, but currently that part is not supported yet.</p>

<p>Kunai is written in C++ and one of the benefits of this is the performance an analyst can obtain using it as library for other projects, also as you can see in the structure picture is intended to be as modular as possible, the main module of Kunai is divided into three important parts:</p>

<ul>
  <li>
    <p>Dalvik parser (<code class="language-plaintext highlighter-rouge">Parser</code> class): this is a Dalvik parser written from scratch that allows analyst to access the different parts from Dalvik’s header, <code class="language-plaintext highlighter-rouge">Parser</code> is divided itself into different classes: <code class="language-plaintext highlighter-rouge">Header</code>, <code class="language-plaintext highlighter-rouge">Strings</code>, <code class="language-plaintext highlighter-rouge">Types</code>, <code class="language-plaintext highlighter-rouge">Protos</code>, <code class="language-plaintext highlighter-rouge">Fields</code>, <code class="language-plaintext highlighter-rouge">Methods</code> and <code class="language-plaintext highlighter-rouge">Classes</code>. These classes offer all the information from the header to the analyst, and they are also subdivided in other classes, you can find more information about Dalvik header on Android’s documentation <a href="https://source.android.com/docs/core/runtime/dex-format">here</a>, also you can see Corkami’s summary of Dalvik Executable format <a href="https://github.com/corkami/pics/blob/master/binary/DEX.png">here</a>. For each DEX analysis, the only action applied to the file is the parsing of its header, no disassembly or further analysis is done in order to keep the performance, in case an analyst just want to read values from the header, other actions over the file can affect the performance of the analysis, and in big DEX files, it can take a significant time to do analysis or cross-reference (xref) analysis.</p>
  </li>
  <li>
    <p>Dalvik disassembler (<code class="language-plaintext highlighter-rouge">DexDisassembler</code> class): Kunai implements a disassembler for Dalvik Bytecode, internally two algorithms are implemented for doing the analysis. One is the <em>linear sweep disassembler</em> which analyze the bytecode from the first to the last byte of a method decoding the dalvik instructions. The other is <em>recursive traversal disassembler</em> which takes all the possible entries from a method, and then starts decoding following the <em>control flow</em> from the method. Any of both algorithm can be selected before applying the disassembly. The disassembler will apply the disassembly process to all the methods from DEX file. Each instruction has a base class <code class="language-plaintext highlighter-rouge">Instruction</code>, and each instruction type is a class that derives from that base. More information from the Instruction formats can be found on Android’s documentation <a href="https://source.android.com/docs/core/runtime/instruction-formats">here</a>.</p>
  </li>
  <li>
    <p>Dalvik analysis (<code class="language-plaintext highlighter-rouge">Analysis</code> class): for a more complete binary analysis, parsing and disassembly is not enough. These classes from the <em>Analysis</em> module offers the analysts the code divided in <code class="language-plaintext highlighter-rouge">MethodAnalysis</code> objects, which contains a <code class="language-plaintext highlighter-rouge">BasicBlocks</code> object with <code class="language-plaintext highlighter-rouge">DVMBasicBlock</code>s for representing the <em>Control-Flow Graph</em> (CFG). Together with the CFG, the <code class="language-plaintext highlighter-rouge">Analysis</code> class offers xrefs for the Dalvik classes, Dalvik methods, Dalvik fields and Dalvik strings, with all this information an analyst can construct a <em>Call Graph</em> (CG). Also it is possible to look for classes or methods using regular expressions, instead of the standardized name (<em>e.g.</em> <code class="language-plaintext highlighter-rouge">LJava/Class/Name;</code>).</p>
  </li>
  <li>
    <p>MjolnIR: while the MLIR based IR is still an ongoing project, it can be used for testing purposes. For using the IR a <code class="language-plaintext highlighter-rouge">Lifter</code> is provided that takes a <code class="language-plaintext highlighter-rouge">MethodAnalysis</code> object, and using the CFG it generates a <code class="language-plaintext highlighter-rouge">FuncOp</code> from MLIR <code class="language-plaintext highlighter-rouge">func</code> dialect divided by <code class="language-plaintext highlighter-rouge">BasicBlocks</code>.</p>
  </li>
</ul>

<h3 id="installation">Installation</h3>

<p>In this section of the post we will see the different ways for compiling and installing Kunai library. In one of the refactoring of Kunai, the compilation chain was moved from a <em>Makefile</em> to <em>CMake</em> allowing the project be easily extended.</p>

<h4 id="compilation-without-mjolnir">Compilation without MjolnIR</h4>

<p>First of all, we have to move to <code class="language-plaintext highlighter-rouge">kunai-lib/</code> folder, and we will run the next command:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>cmake <span class="nt">-B</span> build <span class="nt">-S</span> <span class="nb">.</span>
</code></pre></div></div>

<p>We can choose with <code class="language-plaintext highlighter-rouge">CMAKE_BUILD_TYPE</code> if we want to compile in <code class="language-plaintext highlighter-rouge">Release</code> mode or <code class="language-plaintext highlighter-rouge">Debug</code> mode:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span><span class="k">for </span>Release compilation
<span class="gp">$</span><span class="w"> </span>cmake <span class="nt">-S</span> <span class="nb">.</span> <span class="nt">-B</span> build <span class="nt">-D</span> <span class="nv">CMAKE_BUILD_TYPE</span><span class="o">=</span>Release
<span class="gp">#</span><span class="w"> </span><span class="k">for </span>Debuc compilation
<span class="gp">$</span><span class="w"> </span>cmake <span class="nt">-S</span> <span class="nb">.</span> <span class="nt">-B</span> build <span class="nt">-D</span> <span class="nv">CMAKE_BUILD_TYPE</span><span class="o">=</span>Debug
</code></pre></div></div>

<p>If we want to compile the unit testing files we can set the flag <code class="language-plaintext highlighter-rouge">UNIT_TESTING</code>:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>cmake <span class="nt">-S</span> <span class="nb">.</span> <span class="nt">-B</span> build <span class="nt">-D</span> <span class="nv">CMAKE_BUILD_TYPE</span><span class="o">=</span>DEBUG <span class="nt">-D</span> <span class="nv">UNIT_TESTING</span><span class="o">=</span>ON
</code></pre></div></div>

<p>If you want to speedup the compilation process, you can use the flag <code class="language-plaintext highlighter-rouge">-j</code> or <code class="language-plaintext highlighter-rouge">-j &lt;number of processes&gt;</code>, this will make compilation faster. Finally if you want to install <code class="language-plaintext highlighter-rouge">libkunai.so</code> in your system, you can run the next command:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>cmake <span class="nt">--install</span> build/
</code></pre></div></div>

<h4 id="compilation-with-mjolnir">Compilation with MjolnIR</h4>

<p>MjolnIR depends on MLIR project, so first of all you’ll need to compile MLIR with the LLVM project, this process will take some time and it’s described in the <code class="language-plaintext highlighter-rouge">README.md</code> file from <code class="language-plaintext highlighter-rouge">kunai-lib/</code> folder. If we want to compile Kunai with MjolnIR, we recommend using <code class="language-plaintext highlighter-rouge">clang++</code> as compiler and <code class="language-plaintext highlighter-rouge">lld</code> as linker. Then we will run the next commands:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">#</span><span class="w"> </span>configure the project
<span class="gp">$</span><span class="w"> </span>cmake <span class="nt">-S</span> <span class="nb">.</span> <span class="nt">-B</span> build/ <span class="nt">-DCMAKE_C_COMPILER</span><span class="o">=</span>clang <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>clang++ <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Debug <span class="nt">-DUSE_MJOLNIR</span><span class="o">=</span>ON <span class="nt">-DCMAKE_EXE_LINKER_FLAGS</span><span class="o">=</span><span class="s2">"-fuse-ld=lld"</span> <span class="nt">-DUNIT_TESTING</span><span class="o">=</span>ON
<span class="go">-- The CXX compiler identification is Clang 17.0.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/local/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- C++ compiler ID: Clang
-- C++ compiler version: 17.0.0
-- Build Type: Debug
</span><span class="c">...
</span><span class="gp">#</span><span class="w"> </span>compile it
<span class="gp">$</span><span class="w"> </span>cmake <span class="nt">--build</span> build/ <span class="nt">-j</span>
</code></pre></div></div>

<p>In the previous command, compilation was done with <code class="language-plaintext highlighter-rouge">Debug</code> build type, this can be changed to <code class="language-plaintext highlighter-rouge">Release</code> in case you don’t want to debug anything from the library.</p>

<h2 id="usage">Usage</h2>

<p>Now we will see how we can make use of Kunai, we will do that introducing the examples mentioned at the beginning of the post. First we will learn how we can print the DEX header in a very simple way, and then we will see how we can have a very simple <em>TUI</em> disassembler in less than 219 lines of code.</p>

<h3 id="simple-dex-parsing">Simple DEX Parsing</h3>

<p>As we commented before, the only action Kunai library does when a DEX file is loaded is parsing its header. This avoids the need to wait until all the methods have been disassembled and then analyzed to create the xrefs. For this part of the post, we will use the code under the folder <code class="language-plaintext highlighter-rouge">headers-parser</code> created by Angela.</p>

<p>The first thing we will need in order to analyze a DEX file is provide the path to the file to one of the <code class="language-plaintext highlighter-rouge">static</code> functions from the <code class="language-plaintext highlighter-rouge">Dex</code> class, the name of the function is <code class="language-plaintext highlighter-rouge">parse_dex_file</code> and returns a <code class="language-plaintext highlighter-rouge">std::unique_ptr</code> instance of the <code class="language-plaintext highlighter-rouge">Dex</code> class, this object contains all the necessary classes for analyzing the DEX file.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// parse dex file</span>
<span class="k">auto</span> <span class="n">dex_file</span> <span class="o">=</span> <span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">Dex</span><span class="o">::</span><span class="n">parse_dex_file</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">dex_file</span><span class="o">-&gt;</span><span class="n">get_parsing_correct</span><span class="p">())</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Error analyzing "</span> <span class="o">&lt;&lt;</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">", maybe DEX file is not correct...</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> 
</code></pre></div></div>

<p>In the previous code, we have a call to the mentioned function, giving as parameter the first argument of the parser, here is where it goes the path to the DEX file. In case any error happened during the parsing process, this can be checked with the <code class="language-plaintext highlighter-rouge">get_parsing_correct</code> function which will return <code class="language-plaintext highlighter-rouge">true</code> in case no error happened.</p>

<p>In case no error happened, it means parsing process was successful (easy enough, don’t you think?). Now what we will do is to obtain a pointer to the DEX <code class="language-plaintext highlighter-rouge">Parser</code> object, this object contains all the headers from the DEX file, but due to the complexity of the DEX file format, not all the headers will be covered in this post. To retrieve the <code class="language-plaintext highlighter-rouge">Parser</code> object, just call the function <code class="language-plaintext highlighter-rouge">get_parser</code> from the <code class="language-plaintext highlighter-rouge">Dex</code> object:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">dex_parser</span> <span class="o">=</span> <span class="n">dex_file</span><span class="o">-&gt;</span><span class="n">get_parser</span><span class="p">();</span>
</code></pre></div></div>

<p>This parser will provide us with all the objects that represent each part from the DEX header, the functions from the parser will provide us with references or <code class="language-plaintext highlighter-rouge">const</code> references, in this example we will just retrieve the references. Most of these classes also <code class="language-plaintext highlighter-rouge">override</code> the <code class="language-plaintext highlighter-rouge">operator&lt;&lt;</code> allowing us to print them to <code class="language-plaintext highlighter-rouge">cout</code> easily. This way, we keep for the example the classes just as black boxes, and rely on their implementation for printing them.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// HEADER</span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_header</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_header</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_header</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="c1">// STRINGS</span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_strings</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_strings</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_strings</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="c1">// TYPES</span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_types</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_types</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_types</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="c1">// FIELDS</span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_fields</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_fields</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_fields</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="c1">// CLASSES</span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_classes</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_classes</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_classes</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="c1">// PROTOS </span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_protos</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_protos</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_protos</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="c1">// METHODS</span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_methods</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_methods</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_methods</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="c1">// MAP LIST</span>
<span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_map_list</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_maplist</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">dex_map_list</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
</code></pre></div></div>

<p>As you can see, for each header, we have different <code class="language-plaintext highlighter-rouge">getters</code> to retrieve a reference, you can use <code class="language-plaintext highlighter-rouge">auto</code> from C++ in order to avoid writing the name of the class all the time. In previous implementations, Kunai returned pointers instead of references, in this one, we avoid returning a null value, and you can safely use the object as in this case.</p>

<p>Let’s test this parser in a DEX file, and see what we get as result:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">cd </span>headers-parser/
<span class="gp">$</span><span class="w"> </span>cmake <span class="nt">-B</span> build <span class="nt">-S</span> <span class="nb">.</span> <span class="nt">-DCMAKE_C_COMPILER</span><span class="o">=</span>clang <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>clang++ <span class="nt">-DCMAKE_EXE_LINKER_FLAGS</span><span class="o">=</span><span class="s2">"-fuse-ld=lld-16"</span> <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release
<span class="gp">$</span><span class="w"> </span>cmake <span class="nt">--build</span> build/
<span class="go">[ 50%] Building CXX object CMakeFiles/headers-parser.dir/headers-parser.cpp.o
[100%] Linking CXX executable headers-parser
[100%] Built target headers-parser
</span><span class="gp">$</span><span class="w"> </span>./headers-parser ../../kunai-lib/tests/test-assignment-arith-logic/Main.dex 
<span class="go">DEX Header
Magic: 100(d) 101(e) 120(x) 10(\n) 48(0) 51(3) 53(5) 0 
Checksum:                     148832538
Signature:                    54 101 248 21 82 71 185 249 68 129 234 126 24 8 250 68 254 9 96 173 
File Size:                    1876
Header Size:                  112
Endian Tag:                   305419896
Link Size:                    0
Link Offset:                  0
Map Offset:                   1680
String Ids Size:              41
String Ids Offset:            112
Type Ids Size:                16
Type Ids Offset:              276
Proto Ids Size:               9
Proto Ids Offset:             340
Field Ids Size:               5
Field Ids Offset:             448
Method Ids Size:              12
Method Ids Offset:            488
Class Defs Size:              1
Class Defs Offset:            584
Data Size:                    1260
Data Offset:                  616

Dex Strings
</span><span class="gp">String (0): 1534-&gt;</span><span class="s2">"value"</span>
<span class="gp">String (1): 1525-&gt;</span><span class="s2">"println"</span>
<span class="gp">String (2): 1520-&gt;</span><span class="s2">"out"</span>
<span class="gp">String (3): 1505-&gt;</span><span class="s2">"ojete de vaca"</span>
<span class="gp">String (4): 1469-&gt;</span><span class="s2">"field_int_array"</span>
<span class="gp">String (5): 1458-&gt;</span><span class="s2">"field_int"</span>
<span class="gp">String (6): 1443-&gt;</span><span class="s2">"field_boolean"</span>
<span class="gp">String (7): 1436-&gt;</span><span class="s2">"close"</span>
<span class="gp">String (8): 1290-&gt;</span><span class="s2">"Ljava/lang/System;"</span>
<span class="gp">String (9): 1270-&gt;</span><span class="s2">"Ljava/lang/String;"</span>
<span class="gp">String (10): 1153-&gt;</span><span class="s2">"Ldalvik/annotation/Throws;"</span>
<span class="gp">String (11): 1356-&gt;</span><span class="s2">"VF"</span>
<span class="gp">String (12): 1181-&gt;</span><span class="s2">"Ljava/io/InputStream;"</span>
<span class="gp">String (13): 1496-&gt;</span><span class="s2">"nextInt"</span>
<span class="gp">String (14): 1142-&gt;</span><span class="s2">"J"</span>
<span class="gp">String (15): 1145-&gt;</span><span class="s2">"LMain;"</span>
<span class="gp">String (16): 1204-&gt;</span><span class="s2">"Ljava/io/PrintStream;"</span>
<span class="gp">String (17): 1139-&gt;</span><span class="s2">"I"</span>
<span class="gp">String (18): 1342-&gt;</span><span class="s2">"Test case"</span>
<span class="gp">String (19): 1490-&gt;</span><span class="s2">"main"</span>
<span class="gp">String (20): 1372-&gt;</span><span class="s2">"VZ"</span>
<span class="gp">String (21): 1136-&gt;</span><span class="s2">"F"</span>
<span class="gp">String (22): 1486-&gt;</span><span class="s2">"in"</span>
<span class="gp">String (23): 1250-&gt;</span><span class="s2">"Ljava/lang/Object;"</span>
<span class="gp">String (24): 1368-&gt;</span><span class="s2">"VL"</span>
<span class="gp">String (25): 1331-&gt;</span><span class="s2">"Main.java"</span>
<span class="gp">String (26): 1360-&gt;</span><span class="s2">"VI"</span>
<span class="gp">String (27): 1118-&gt;</span><span class="s2">"&lt;clinit&gt;"</span>
<span class="gp">String (28): 1379-&gt;</span><span class="s2">"[I"</span>
<span class="gp">String (29): 1541-&gt;</span><span class="s2">"~~D8{"</span>compilation-mode<span class="s2">":"</span>debug<span class="s2">","</span>min-api<span class="s2">":1,"</span>version<span class="s2">":"</span>1.5.13-q1<span class="s2">"}"</span>
<span class="gp">String (30): 1128-&gt;</span><span class="s2">"&lt;init&gt;"</span>
<span class="gp">String (31): 1364-&gt;</span><span class="s2">"VJ"</span>
<span class="gp">String (32): 1376-&gt;</span><span class="s2">"Z"</span>
<span class="gp">String (33): 1383-&gt;</span><span class="s2">"[Ljava/lang/String;"</span>
<span class="gp">String (34): 1353-&gt;</span><span class="s2">"V"</span>
<span class="gp">String (35): 1412-&gt;</span><span class="s2">"c &lt;= 20"</span>
<span class="gp">String (36): 1227-&gt;</span><span class="s2">"Ljava/lang/Exception;"</span>
<span class="gp">String (37): 1404-&gt;</span><span class="s2">"c &lt;= 0"</span>
<span class="gp">String (38): 1421-&gt;</span><span class="s2">"c &gt; 0"</span>
<span class="gp">String (39): 1310-&gt;</span><span class="s2">"Ljava/util/Scanner;"</span>
<span class="gp">String (40): 1428-&gt;</span><span class="s2">"c &gt; 20"</span>
<span class="go">
DEX Types:
</span><span class="gp">Type (0) -&gt;</span><span class="w"> </span><span class="s2">"float"</span>
<span class="gp">Type (1) -&gt;</span><span class="w"> </span><span class="s2">"int"</span>
<span class="gp">Type (2) -&gt;</span><span class="w"> </span><span class="s2">"long"</span>
<span class="gp">Type (3) -&gt;</span><span class="w"> </span><span class="s2">"Main"</span>
<span class="gp">Type (4) -&gt;</span><span class="w"> </span><span class="s2">"dalvik.annotation.Throws"</span>
<span class="gp">Type (5) -&gt;</span><span class="w"> </span><span class="s2">"java.io.InputStream"</span>
<span class="gp">Type (6) -&gt;</span><span class="w"> </span><span class="s2">"java.io.PrintStream"</span>
<span class="gp">Type (7) -&gt;</span><span class="w"> </span><span class="s2">"java.lang.Exception"</span>
<span class="gp">Type (8) -&gt;</span><span class="w"> </span><span class="s2">"java.lang.Object"</span>
<span class="gp">Type (9) -&gt;</span><span class="w"> </span><span class="s2">"java.lang.String"</span>
<span class="gp">Type (10) -&gt;</span><span class="w"> </span><span class="s2">"java.lang.System"</span>
<span class="gp">Type (11) -&gt;</span><span class="w"> </span><span class="s2">"java.util.Scanner"</span>
<span class="gp">Type (12) -&gt;</span><span class="w"> </span><span class="s2">"void"</span>
<span class="gp">Type (13) -&gt;</span><span class="w"> </span><span class="s2">"boolean"</span>
<span class="gp">Type (14) -&gt;</span><span class="w"> </span><span class="s2">"int[]"</span>
<span class="gp">Type (15) -&gt;</span><span class="w"> </span><span class="s2">"java.lang.String[]"</span>
<span class="go">
DEX Fields:
</span><span class="gp">Field(0): LMain;</span>-&gt;field_boolean Z
<span class="gp">Field(1): LMain;</span>-&gt;field_int I
<span class="gp">Field(2): LMain;</span>-&gt;field_int_array <span class="o">[</span>I
<span class="gp">Field(3): Ljava/lang/System;</span>-&gt;in Ljava/io/InputStream<span class="p">;</span>
<span class="gp">Field(4): Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span>
<span class="go">
DEX Classes:
Class(0): Main, Superclass: java.lang.Object, Source file: Main.java, Access flags: public

DEX Protos:
Proto (0): I
Proto (1): V
Proto (2): VF
Proto (3): VI
Proto (4): VJ
Proto (5): VL
Proto (6): VL
Proto (7): VZ
Proto (8): VL

DEX Methods:
</span><span class="gp">Method(0): void Main-&gt;</span>&lt;clinit&gt;<span class="o">()</span>, Access Flags: final constructor
<span class="gp">Method(1): void Main-&gt;</span>&lt;init&gt;<span class="o">()</span>, Access Flags: public constructor
<span class="gp">Method(2): void Main-&gt;</span>main<span class="o">(</span>java.lang.String[]<span class="o">)</span>, Access Flags: public final
<span class="gp">Method(3): void java.io.PrintStream-&gt;</span>println<span class="o">(</span>float<span class="o">)</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(4): void java.io.PrintStream-&gt;</span>println<span class="o">(</span>int<span class="o">)</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(5): void java.io.PrintStream-&gt;</span>println<span class="o">(</span>long<span class="o">)</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(6): void java.io.PrintStream-&gt;</span>println<span class="o">(</span>java.lang.String<span class="o">)</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(7): void java.io.PrintStream-&gt;</span>println<span class="o">(</span>boolean<span class="o">)</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(8): void java.lang.Object-&gt;</span>&lt;init&gt;<span class="o">()</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(9): void java.util.Scanner-&gt;</span>&lt;init&gt;<span class="o">(</span>java.io.InputStream<span class="o">)</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(10): void java.util.Scanner-&gt;</span>close<span class="o">()</span>, Access Flags: &lt;External Method&gt; 
<span class="gp">Method(11): int java.util.Scanner-&gt;</span>nextInt<span class="o">()</span>, Access Flags: &lt;External Method&gt; 
<span class="go">
DEX Map List:
Map item (0): TYPE_MAP_LIST, Size: 1, Offset: 1680
Map item (1): TYPE_ANNOTATIONS_DIRECTORY_ITEM, Size: 1, Offset: 1656
Map item (2): TYPE_ANNOTATION_SET_ITEM, Size: 2, Offset: 1644
Map item (3): TYPE_HEADER_ITEM, Size: 1, Offset: 0
Map item (4): TYPE_STRING_ID_ITEM, Size: 41, Offset: 112
Map item (5): TYPE_TYPE_ID_ITEM, Size: 16, Offset: 276
Map item (6): TYPE_TYPE_LIST, Size: 7, Offset: 1064
Map item (7): TYPE_CLASS_DATA_ITEM, Size: 1, Offset: 1617
Map item (8): TYPE_PROTO_ID_ITEM, Size: 9, Offset: 340
Map item (9): TYPE_CODE_ITEM, Size: 3, Offset: 616
Map item (10): TYPE_FIELD_ID_ITEM, Size: 5, Offset: 448
Map item (11): TYPE_STRING_DATA_ITEM, Size: 41, Offset: 1118
Map item (12): TYPE_METHOD_ID_ITEM, Size: 12, Offset: 488
Map item (13): TYPE_DEBUG_INFO_ITEM, Size: 3, Offset: 1020
Map item (14): TYPE_CLASS_DEF_ITEM, Size: 1, Offset: 584
Map item (15): TYPE_ANNOTATION_ITEM, Size: 1, Offset: 160
</span></code></pre></div></div>

<p>As you can see, in this case we obtain a very verbose output, since by default, printing the object will use the default printer that just dumps all the information about the object itself. In the next section we will see how to make a more specific printing of the headers, checking some internal structures.</p>

<p>You can find the whole code for this example <a href="https://github.com/Fare9/KUNAI-static-analyzer/blob/refactoring/headers-parser/headers-parser.cpp">here</a></p>

<h3 id="specific-dex-parsing">Specific DEX Parsing</h3>

<p>In the previous example we presented the parser, and we showed a way for printing information passing the object to the <code class="language-plaintext highlighter-rouge">std::cout</code>, invoking the default printer from the object. This time we will change it in order to show how we can dig into the structures the parser offers. In this example, we will just print some data from the header, and then some information about the classes.</p>

<p>The beginning of the code is exactly as before:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// parse dex file</span>
<span class="k">auto</span> <span class="n">dex_file</span> <span class="o">=</span> <span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">Dex</span><span class="o">::</span><span class="n">parse_dex_file</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">dex_file</span><span class="o">-&gt;</span><span class="n">get_parsing_correct</span><span class="p">())</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Error analyzing "</span> <span class="o">&lt;&lt;</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">", maybe DEX file is not correct...</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> 
</code></pre></div></div>

<p>This will be basic in all the analysis we write with Kunai, since it’s the initializer for the DEX structures. Again we will retrieve the <code class="language-plaintext highlighter-rouge">Parser</code> object, but also the <code class="language-plaintext highlighter-rouge">Header</code> object as a constant reference:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// get pointer to parser</span>
<span class="k">auto</span> <span class="n">dex_parser</span> <span class="o">=</span> <span class="n">dex_file</span><span class="o">-&gt;</span><span class="n">get_parser</span><span class="p">();</span>

<span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">dex_header</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_header_const</span><span class="p">();</span>
</code></pre></div></div>

<p>From the <code class="language-plaintext highlighter-rouge">Header</code> object we can access the <code class="language-plaintext highlighter-rouge">dexheader_t</code> which is a structure with all the fields from the header, we will print the checksum, and the printable characters from the <em>magic</em> bytes:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"DEX Checksum: "</span> <span class="o">&lt;&lt;</span> <span class="n">dex_header</span><span class="p">.</span><span class="n">get_dex_header_const</span><span class="p">().</span><span class="n">checksum</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>

<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"DEX Magic: "</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">val</span> <span class="o">:</span> <span class="n">dex_header</span><span class="p">.</span><span class="n">get_dex_header_const</span><span class="p">().</span><span class="n">magic</span><span class="p">)</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">isprint</span><span class="p">(</span><span class="n">val</span><span class="p">))</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">val</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
</code></pre></div></div>

<p>Now we will retrieve the <code class="language-plaintext highlighter-rouge">Classes</code> object, but this time instead of printing it directly, we will go over different internal components, for example the <code class="language-plaintext highlighter-rouge">ClassDef</code> objects which contain all the information about the class, the <code class="language-plaintext highlighter-rouge">DVMClass</code> which holds the number of the class and its type of data, the access flags, and other information about the class:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="o">&amp;</span> <span class="n">classes</span> <span class="o">=</span> <span class="n">dex_parser</span><span class="o">-&gt;</span><span class="n">get_classes</span><span class="p">();</span>

<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span> <span class="n">classdef</span> <span class="o">:</span> <span class="n">classes</span><span class="p">.</span><span class="n">get_classdefs</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">class_data</span> <span class="o">=</span> <span class="n">classdef</span><span class="o">-&gt;</span><span class="n">get_class_idx</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">class_data</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Object Type: "</span> <span class="o">&lt;&lt;</span> <span class="n">class_data</span><span class="o">-&gt;</span><span class="n">print_type</span><span class="p">()</span> 
        <span class="o">&lt;&lt;</span> <span class="s">", Name: "</span> <span class="o">&lt;&lt;</span> <span class="n">class_data</span><span class="o">-&gt;</span><span class="n">get_name</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>

    <span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span> <span class="n">source_file</span> <span class="o">=</span> <span class="n">classdef</span><span class="o">-&gt;</span><span class="n">get_source_file</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">source_file</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Source file: "</span> <span class="o">&lt;&lt;</span> <span class="n">source_file</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Access Flags: "</span> <span class="o">&lt;&lt;</span> <span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">DalvikOpcodes</span><span class="o">::</span><span class="n">get_access_flags_str</span><span class="p">(</span><span class="n">classdef</span><span class="o">-&gt;</span><span class="n">get_access_flags</span><span class="p">())</span>
        <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    
    <span class="k">auto</span> <span class="o">&amp;</span> <span class="n">class_data_item</span> <span class="o">=</span> <span class="n">classdef</span><span class="o">-&gt;</span><span class="n">get_class_data_item</span><span class="p">();</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Number of static fields: "</span> <span class="o">&lt;&lt;</span> <span class="n">class_data_item</span><span class="p">.</span><span class="n">get_number_of_static_fields</span><span class="p">()</span>
                <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">Number of instance fields: "</span> <span class="o">&lt;&lt;</span> <span class="n">class_data_item</span><span class="p">.</span><span class="n">get_number_of_instance_fields</span><span class="p">()</span>
                <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">Number of direct methods: "</span> <span class="o">&lt;&lt;</span> <span class="n">class_data_item</span><span class="p">.</span><span class="n">get_number_of_direct_methods</span><span class="p">()</span>
                <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">Number of virtual methods: "</span> <span class="o">&lt;&lt;</span> <span class="n">class_data_item</span><span class="p">.</span><span class="n">get_number_of_virtual_methods</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    
    <span class="k">auto</span> <span class="n">superclass</span> <span class="o">=</span> <span class="n">classdef</span><span class="o">-&gt;</span><span class="n">get_superclass</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">superclass</span><span class="p">)</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Object Type: "</span> <span class="o">&lt;&lt;</span> <span class="n">superclass</span><span class="o">-&gt;</span><span class="n">print_type</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">", Name: "</span> <span class="o">&lt;&lt;</span> <span class="n">superclass</span><span class="o">-&gt;</span><span class="n">get_name</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In some cases where the object is present, we will have a reference to the object, in other cases, the value is not always present in a DEX file, and we will retrieve a pointer, in those cases it is better to check the pointer is correct. Now let’s compile and run it to see what we get:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>cmake <span class="nt">-B</span> build <span class="nt">-S</span> <span class="nb">.</span> <span class="nt">-DCMAKE_C_COMPILER</span><span class="o">=</span>clang <span class="nt">-DCMAKE_CXX_COMPILER</span><span class="o">=</span>clang++ <span class="nt">-DCMAKE_EXE_LINKER_FLAGS</span><span class="o">=</span><span class="s2">"-fuse-ld=lld-16"</span> <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release
<span class="gp">$</span><span class="w"> </span>cmake <span class="nt">--build</span> build/
<span class="gp">$</span><span class="w"> </span><span class="nb">cd </span>build
<span class="gp">$</span><span class="w"> </span>./header-simple-printer ../../kunai-lib/tests/test-assignment-arith-logic/Main.dex 
<span class="go">DEX Checksum: 148832538
DEX Magic: dex035
</span><span class="gp">Object Type: Class, Name: LMain;</span><span class="w">
</span><span class="go">Source file: Main.java
Access Flags: public
Number of static fields: 3
Number of instance fields: 0
Number of direct methods: 3
Number of virtual methods: 0
</span><span class="gp">Object Type: Class, Name: Ljava/lang/Object;</span><span class="w">
</span></code></pre></div></div>

<p>You can find the whole code for this example <a href="https://github.com/Fare9/KUNAI-static-analyzer/blob/refactoring/examples/header-simple-printer.cpp">here</a>.</p>

<h3 id="a-simple-disassembler">A Simple Disassembler</h3>

<p>We will move now to the last part of this post where we will show how a very simple disassembler is written in 220 lines of C++ code, with the necessary code to print it in a cool way!</p>

<p>This disassembler is intended to allow user printing different output formats, also it allows using the different disassembly algorithms from Kunai. So first of all our code must manage all these command line stuff, we will use a very simple command line parsing:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">/// use the recursive disassembler?</span>
    <span class="kt">bool</span> <span class="n">use_recursive</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
    <span class="kt">bool</span> <span class="n">show_blocks</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
    <span class="kt">bool</span> <span class="n">show_plot</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">strcmp</span><span class="p">(</span><span class="s">"-h"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])))</span>
    <span class="p">{</span>
        <span class="n">show_help</span><span class="p">(</span><span class="n">argv</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// check that 4 arguments were given</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">show_help</span><span class="p">(</span><span class="n">argv</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// check if one argument more was given</span>
    <span class="c1">// check if it is correct</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&gt;</span> <span class="mi">4</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string_view</span><span class="o">&gt;</span> <span class="n">optional_args</span><span class="p">(</span><span class="n">argv</span> <span class="o">+</span> <span class="mi">4</span><span class="p">,</span> <span class="n">argv</span> <span class="o">+</span> <span class="n">argc</span><span class="p">);</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="n">val</span> <span class="o">:</span> <span class="n">optional_args</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">==</span> <span class="s">"-r"</span><span class="p">)</span>
                <span class="n">use_recursive</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">==</span> <span class="s">"-b"</span><span class="p">)</span>
                <span class="n">show_blocks</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">==</span> <span class="s">"-p"</span><span class="p">)</span>
                <span class="n">show_plot</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>With this code we will store in different <code class="language-plaintext highlighter-rouge">bool</code> variables the different options, for example if user specifies <code class="language-plaintext highlighter-rouge">-r</code> we will set <code class="language-plaintext highlighter-rouge">use_recursive</code> to <code class="language-plaintext highlighter-rouge">true</code> and later we will configure Kunai to use this algorithm, the other options will be used to show the blocks from the method, instead of a linear disassembly, or if the user wants to plot the graph to a <em>dot</em> file. In case we find any kind of error, we print a help message using the function <code class="language-plaintext highlighter-rouge">show_help</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">show_help</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"[-] USAGE: "</span> <span class="o">&lt;&lt;</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">" &lt;dex_file&gt; &lt;class_name&gt; &lt;method_name&gt; [-r]</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">&lt;dex_file&gt;: dex file to disassembly</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">&lt;class_name&gt;: name of the class to extract</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">&lt;method_name&gt;: name of the method to extract</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">[-r]: optional argument, use recursive disassembly algorithm</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">[-b]: show the instructions as basic blocks</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\t</span><span class="s">[-p]: show a plot with the blocks in .dot format</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>After this, we will take the class name, and method name to analyze, we will also set the level of logging in order to see more messages from the log mechanism of Kunai:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">/// watch info and error messages from Kunai</span>
<span class="n">spdlog</span><span class="o">::</span><span class="n">set_level</span><span class="p">(</span><span class="n">spdlog</span><span class="o">::</span><span class="n">level</span><span class="o">::</span><span class="n">err</span><span class="p">);</span>

<span class="c1">/// class name and method name</span>
<span class="k">auto</span> <span class="n">class_name</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
<span class="k">auto</span> <span class="n">method_name</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
</code></pre></div></div>

<p>As we have previously seen, we need to analyze the DEX file, and for doing that, we again use the <code class="language-plaintext highlighter-rouge">static</code> function from <code class="language-plaintext highlighter-rouge">Dex</code> class, <code class="language-plaintext highlighter-rouge">parse_dex_file</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// now the dex file...</span>
<span class="k">auto</span> <span class="n">dex_file</span> <span class="o">=</span> <span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">Dex</span><span class="o">::</span><span class="n">parse_dex_file</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">dex_file</span><span class="o">-&gt;</span><span class="n">get_parsing_correct</span><span class="p">())</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Error analyzing "</span> <span class="o">&lt;&lt;</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">", maybe DEX file is not correct...</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And for using the disassembler, we have to retrieve the <code class="language-plaintext highlighter-rouge">DexDisassembler</code> object from the previous <code class="language-plaintext highlighter-rouge">Dex</code> object, for doing that we will call <code class="language-plaintext highlighter-rouge">get_dex_disassembler</code> that will return a pointer to the object, then if the user decided to use the recursive disassembly algorithm, we will choose it with the function <code class="language-plaintext highlighter-rouge">set_disassembly_algorithm</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// obtain the disassembler from the DEX object</span>
<span class="k">auto</span> <span class="n">dex_disassembler</span> <span class="o">=</span> <span class="n">dex_file</span><span class="o">-&gt;</span><span class="n">get_dex_disassembler</span><span class="p">();</span>

<span class="c1">// if recursive disassembly is requested</span>
<span class="c1">// change the disassembly method</span>
<span class="k">if</span> <span class="p">(</span><span class="n">use_recursive</span><span class="p">)</span>
    <span class="n">dex_disassembler</span><span class="o">-&gt;</span><span class="n">set_disassembly_algorithm</span><span class="p">(</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">DexDisassembler</span><span class="o">::</span><span class="n">disassembly_algorithm</span><span class="o">::</span><span class="n">RECURSIVE_TRAVERSAL_ALGORITHM</span><span class="p">);</span>
</code></pre></div></div>

<p>The previous code just retrieves the disassembler, but it doesn’t apply the disassembly process yet, we will need to call <code class="language-plaintext highlighter-rouge">disassembly_dex</code> for doing it. Before digging deeper into the disassembler, we recommend reading the function <code class="language-plaintext highlighter-rouge">show_instruction</code>, which is the one which manages the printing of the instruction in a <em>cool</em> way, showing first the opcodes from the instruction and then printing the instruction as a string:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">show_instruction</span><span class="p">(</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">Instruction</span> <span class="o">*</span><span class="n">instr</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">right</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setfill</span><span class="p">(</span><span class="sc">'0'</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setw</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">hex</span> <span class="o">&lt;&lt;</span> <span class="n">instr</span><span class="o">-&gt;</span><span class="n">get_address</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"  "</span><span class="p">;</span>

    <span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">opcodes</span> <span class="o">=</span> <span class="n">instr</span><span class="o">-&gt;</span><span class="n">get_opcodes</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">opcodes</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">8</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">auto</span> <span class="n">remaining</span> <span class="o">=</span> <span class="mi">8</span> <span class="o">-</span> <span class="p">(</span><span class="n">opcodes</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">%</span> <span class="mi">8</span><span class="p">);</span>

        <span class="kt">size_t</span> <span class="n">aux</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

        <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="n">opcode</span> <span class="o">:</span> <span class="n">opcodes</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">right</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setfill</span><span class="p">(</span><span class="sc">'0'</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setw</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">hex</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">opcode</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>
            <span class="n">aux</span><span class="o">++</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">aux</span> <span class="o">%</span> <span class="mi">8</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span>
                          <span class="o">&lt;&lt;</span> <span class="s">"          "</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>

        <span class="k">for</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint8_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">remaining</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"   "</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span>
    <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="n">opcode</span> <span class="o">:</span> <span class="n">opcodes</span><span class="p">)</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">right</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setfill</span><span class="p">(</span><span class="sc">'0'</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setw</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">hex</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">opcode</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>

        <span class="k">for</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">uint8_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">remaining_size</span> <span class="o">=</span> <span class="mi">8</span> <span class="o">-</span> <span class="n">opcodes</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">remaining_size</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"   "</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">instr</span><span class="o">-&gt;</span><span class="n">print_instruction</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="printing-line-by-line">Printing line by line</h4>

<p>Now that we have left behind the <em>cool printing</em> we can continue, if we remember, at the beginning we checked if the user wanted to print basic blocks, or plot it as a dot file. In case none of those options is chosen, we just print the instructions from first to last, this is done with the next code:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">/// we have to apply the disassembly ourselves since</span>
<span class="c1">/// the library only applies parsing</span>
<span class="n">dex_disassembler</span><span class="o">-&gt;</span><span class="n">disassembly_dex</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">dex_disassembler</span><span class="o">-&gt;</span><span class="n">correct_disassembly</span><span class="p">())</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Error in the disassembly of "</span> <span class="o">&lt;&lt;</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> 
        <span class="o">&lt;&lt;</span> <span class="s">", maybe some method was incorrect...</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Before we just retrieved the disassembler, but we didn’t apply the disassembly process. For doing this, we will call <code class="language-plaintext highlighter-rouge">disassembly_dex</code>, this will disassemble the whole DEX file. Then we can check if the disassembly process was correct calling <code class="language-plaintext highlighter-rouge">correct_disassembly</code>.</p>

<p>We are almost finishing this part, we just need to retrieve the instructions which are stored in a <code class="language-plaintext highlighter-rouge">std::unordered_map</code>, then we will go over that structure looking for the class and method user provided at the beginning of the code, and once it is found, we will show all the instructions one by one:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">dex_instructions</span> <span class="o">=</span> <span class="n">dex_disassembler</span><span class="o">-&gt;</span><span class="n">get_dex_instructions</span><span class="p">();</span>
<span class="c1">/// dex instructions contain the next pair:</span>
<span class="c1">///     - encoded_method : instructions from method</span>
<span class="c1">/// we will check for each one if class name and method names</span>
<span class="c1">/// are correct</span>
<span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">disassembly</span> <span class="o">:</span> <span class="n">dex_instructions</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">auto</span> <span class="n">encoded_method</span> <span class="o">=</span> <span class="n">disassembly</span><span class="p">.</span><span class="n">first</span><span class="p">;</span>
    <span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">instrs</span> <span class="o">=</span> <span class="n">disassembly</span><span class="p">.</span><span class="n">second</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">cls_</span> <span class="o">=</span> <span class="k">reinterpret_cast</span><span class="o">&lt;</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">DVMClass</span> <span class="o">*&gt;</span><span class="p">(</span><span class="n">encoded_method</span><span class="o">-&gt;</span><span class="n">getMethodID</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_class</span><span class="p">());</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">cls_</span> <span class="o">==</span> <span class="nb">nullptr</span><span class="p">)</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">cls_</span><span class="o">-&gt;</span><span class="n">get_name</span><span class="p">()</span> <span class="o">!=</span> <span class="n">class_name</span> <span class="o">||</span>
        <span class="n">encoded_method</span><span class="o">-&gt;</span><span class="n">getMethodID</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_name</span><span class="p">()</span> <span class="o">!=</span> <span class="n">method_name</span><span class="p">)</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">encoded_method</span><span class="o">-&gt;</span><span class="n">getMethodID</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">pretty_method</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">instr</span> <span class="o">:</span> <span class="n">instrs</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">show_instruction</span><span class="p">(</span><span class="n">instr</span><span class="p">.</span><span class="n">get</span><span class="p">());</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The code is pretty straightforward, once we find the method, we just go over each instruction calling the function <code class="language-plaintext highlighter-rouge">show_instruction</code>.</p>

<h4 id="printing-basic-blocks-or-plot">Printing basic blocks or Plot</h4>

<p>Now we will see the part of the code that prints the basic blocks, or dumps the plot into a <code class="language-plaintext highlighter-rouge">.dot</code> file. For obtaining the basic blocks, we will use the third part of Kunai, the <code class="language-plaintext highlighter-rouge">Analysis</code> class. For using the analysis, we will have to call the function <code class="language-plaintext highlighter-rouge">get_analysis</code> from the <code class="language-plaintext highlighter-rouge">Dex</code> object. This function has one parameter, this parameter is a boolean value that instructs Kunai whether to perform deeper analysis or not. If enabled, the analysis includes obtaining <code class="language-plaintext highlighter-rouge">xrefs</code>. In this case, <code class="language-plaintext highlighter-rouge">xrefs</code> are not needed, so we will specify <code class="language-plaintext highlighter-rouge">false</code>. Internally Kunai will provide the <code class="language-plaintext highlighter-rouge">Analysis</code> object with the disassembler, so the task is easier :D.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">analysis</span> <span class="o">=</span> <span class="n">dex_file</span><span class="o">-&gt;</span><span class="n">get_analysis</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
</code></pre></div></div>

<p>The next code will go over the methods looking for the method we want to dump, it is pretty similar to the previous code we wrote for the simpler printing:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">methods</span> <span class="o">=</span> <span class="n">analysis</span><span class="o">-&gt;</span><span class="n">get_methods</span><span class="p">();</span>

<span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">method</span> <span class="o">:</span> <span class="n">methods</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">method</span><span class="p">.</span><span class="n">second</span><span class="o">-&gt;</span><span class="n">external</span><span class="p">())</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">encoded_method</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">EncodedMethod</span> <span class="o">*&gt;</span><span class="p">(</span><span class="n">method</span><span class="p">.</span><span class="n">second</span><span class="o">-&gt;</span><span class="n">get_encoded_method</span><span class="p">());</span>
    <span class="k">auto</span> <span class="n">cls_</span> <span class="o">=</span> <span class="k">reinterpret_cast</span><span class="o">&lt;</span><span class="n">KUNAI</span><span class="o">::</span><span class="n">DEX</span><span class="o">::</span><span class="n">DVMClass</span> <span class="o">*&gt;</span><span class="p">(</span><span class="n">encoded_method</span><span class="o">-&gt;</span><span class="n">getMethodID</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_class</span><span class="p">());</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">cls_</span> <span class="o">==</span> <span class="nb">nullptr</span><span class="p">)</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">cls_</span><span class="o">-&gt;</span><span class="n">get_name</span><span class="p">()</span> <span class="o">!=</span> <span class="n">class_name</span> <span class="o">||</span>
        <span class="n">encoded_method</span><span class="o">-&gt;</span><span class="n">getMethodID</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_name</span><span class="p">()</span> <span class="o">!=</span> <span class="n">method_name</span><span class="p">)</span>
        <span class="k">continue</span><span class="p">;</span>

    <span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Once we have found the method, we have two different codes. One of the codes will print the basic blocks in the terminal, and will also show the edges between the different basic blocks, the other will just dump the code into a <code class="language-plaintext highlighter-rouge">.dot</code> file.</p>

<h5 id="dumping-basic-blocks">Dumping Basic Blocks</h5>

<p>Since we already have a <code class="language-plaintext highlighter-rouge">MethodAnalysis</code> block, we will go over the different basic blocks. Basic Blocks in Kunai are stored together with two special blocks, one is a <code class="language-plaintext highlighter-rouge">start</code> block, and the other is an <code class="language-plaintext highlighter-rouge">end</code> block. This is made for fulfilling the requirements of what a CFG is (having an entry and end block). Also in Dalvik we find <code class="language-plaintext highlighter-rouge">try</code> and <code class="language-plaintext highlighter-rouge">catch</code> blocks, we will print them in a different way too:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">blocks</span> <span class="o">=</span> <span class="n">method</span><span class="p">.</span><span class="n">second</span><span class="o">-&gt;</span><span class="n">get_basic_blocks</span><span class="p">();</span>

<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">encoded_method</span><span class="o">-&gt;</span><span class="n">getMethodID</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">pretty_method</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

<span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="n">block</span> <span class="o">:</span> <span class="n">blocks</span><span class="p">.</span><span class="n">get_nodes</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">is_start_block</span><span class="p">())</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"BB-Start Block</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">is_end_block</span><span class="p">())</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"BB-End Block</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">is_try_block</span><span class="p">())</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"BB-"</span> <span class="o">&lt;&lt;</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_first_address</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">" (try block)"</span>
                    <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">block</span><span class="o">-&gt;</span><span class="n">is_catch_block</span><span class="p">())</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"BB-"</span> <span class="o">&lt;&lt;</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_first_address</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">" (catch block)"</span>
                    <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">else</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"BB-"</span> <span class="o">&lt;&lt;</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_first_address</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">instr</span> <span class="o">:</span> <span class="n">block</span><span class="o">-&gt;</span><span class="n">get_instructions</span><span class="p">())</span>
        <span class="n">show_instruction</span><span class="p">(</span><span class="n">instr</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Edges: "</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span> <span class="n">edge</span> <span class="o">:</span> <span class="n">blocks</span><span class="p">.</span><span class="n">get_edges</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">edge</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">is_start_block</span><span class="p">()</span> <span class="o">||</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">edge</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">is_end_block</span><span class="p">())</span>
        <span class="k">continue</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"BB-"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">edge</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">get_first_address</span><span class="p">()</span> 
        <span class="o">&lt;&lt;</span> <span class="s">" -&gt; BB-"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">edge</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">get_first_address</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>For printing the instructions we will use the code we previously saw.</p>

<h5 id="dumping-a-dot-file">Dumping a Dot file</h5>

<p>Finally and to finish, we give the chance for dumping a <code class="language-plaintext highlighter-rouge">.dot</code> file. The <code class="language-plaintext highlighter-rouge">MethodAnalysis</code> object has a built-in function that allows doing this in a simple way.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">file_name</span> <span class="o">=</span> <span class="n">class_name</span> <span class="o">+</span> <span class="s">"."</span> <span class="o">+</span> <span class="n">method_name</span> <span class="o">+</span> <span class="s">".dot"</span><span class="p">;</span>
<span class="n">method</span><span class="p">.</span><span class="n">second</span><span class="o">-&gt;</span><span class="n">dump_dot_file</span><span class="p">(</span><span class="n">file_name</span><span class="p">);</span>
</code></pre></div></div>

<h4 id="trying-the-disassembler">Trying the Disassembler</h4>

<p>Now we will try the disassembler, and we will show the different options.</p>

<p>First of all we will show the disassembly of a simple function, the Java code used for the test is the next one:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.util.Scanner</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">strArr</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
        <span class="nc">Scanner</span> <span class="n">scanner</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Scanner</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">in</span><span class="o">);</span>
        <span class="kt">int</span> <span class="n">nextInt</span> <span class="o">=</span> <span class="n">scanner</span><span class="o">.</span><span class="na">nextInt</span><span class="o">();</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">nextInt</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"You gave me value 0..."</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Not a bad value :D..."</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">try</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mi">3</span> <span class="o">/</span> <span class="n">nextInt</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">ArithmeticException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Divided by zero operation cannot possible"</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="n">scanner</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Now we will apply the disassembly to that main function, in this case, this <em>plain</em> disassembly doesn’t tell us about the <code class="language-plaintext highlighter-rouge">try</code> or <code class="language-plaintext highlighter-rouge">catch</code> blocks.</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nv">$ </span>./dalvik-disassembler ../../kunai-lib/tests/test-try-catch/Main.dex <span class="s2">"LMain;"</span>  main
<span class="gp">void Main-&gt;</span>main<span class="o">(</span>java.lang.String[]<span class="o">)</span>
<span class="go">00000000  22 03 0a 00             new-instance v3, java.util.Scanner (10)
</span><span class="gp">00000004  62 00 00 00             sget-object v0, Ljava/lang/System;</span>-&gt;in Ljava/io/InputStream<span class="p">;</span> <span class="o">(</span>0<span class="o">)</span>
<span class="gp">00000008  70 20 05 00 03 00       invoke-direct {v3, v0}, void java.util.Scanner-&gt;</span>&lt;init&gt;<span class="o">(</span>java.io.InputStream<span class="o">)</span>
<span class="gp">0000000e  6e 10 07 00 03 00       invoke-virtual {v3}, int java.util.Scanner-&gt;</span>nextInt<span class="o">()</span>
<span class="go">00000014  0a 00                   move-result v0
00000016  00 00                   nop
00000018  00 00                   nop
0000001a  39 00 0a 00             if-nez v0, 10
</span><span class="gp">0000001e  62 01 01 00             sget-object v1, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="go">00000022  1a 02 12 00             const-string v2, "You gave me value 0..." (18)
</span><span class="gp">00000026  6e 20 03 00 21 00       invoke-virtual {v1, v2}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>java.lang.String<span class="o">)</span>
<span class="go">0000002c  28 08                   goto 60
</span><span class="gp">0000002e  62 01 01 00             sget-object v1, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="go">00000032  1a 02 0e 00             const-string v2, "Not a bad value :D..." (14)
</span><span class="gp">00000036  6e 20 03 00 21 00       invoke-virtual {v1, v2}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>java.lang.String<span class="o">)</span>
<span class="go">0000003c  12 31                   const/4 v1, 3
0000003e  b3 01                   div-int/2addr v1, v0
</span><span class="gp">00000040  62 00 01 00             sget-object v0, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="gp">00000044  6e 20 02 00 10 00       invoke-virtual {v0, v1}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>int<span class="o">)</span>
<span class="go">0000004a  28 09                   goto 92
0000004c  0d 00                   move-exception v0
</span><span class="gp">0000004e  62 00 01 00             sget-object v0, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="go">00000052  1a 01 01 00             const-string v1, "Divided by zero operation cannot possible" (1)
</span><span class="gp">00000056  6e 20 03 00 10 00       invoke-virtual {v0, v1}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>java.lang.String<span class="o">)</span>
<span class="gp">0000005c  6e 10 06 00 03 00       invoke-virtual {v3}, void java.util.Scanner-&gt;</span>close<span class="o">()</span>
<span class="go">00000062  0e 00                   return-void
</span></code></pre></div></div>

<p>Now we can specify the disassembler to show the basic blocks and the connection between the basic blocks.</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>./dalvik-disassembler ../../kunai-lib/tests/test-try-catch/Main.dex <span class="s2">"LMain;"</span>  main <span class="nt">-b</span>
<span class="go">[2023-06-10 21:46:00.208] [stderr] [info] Analysis: correctly added parser to analysis object
</span><span class="gp">void Main-&gt;</span>main<span class="o">(</span>java.lang.String[]<span class="o">)</span>
<span class="go">BB-Start Block
BB-0
00000000  22 03 0a 00             new-instance v3, java.util.Scanner (10)
</span><span class="gp">00000004  62 00 00 00             sget-object v0, Ljava/lang/System;</span>-&gt;in Ljava/io/InputStream<span class="p">;</span> <span class="o">(</span>0<span class="o">)</span>
<span class="gp">00000008  70 20 05 00 03 00       invoke-direct {v3, v0}, void java.util.Scanner-&gt;</span>&lt;init&gt;<span class="o">(</span>java.io.InputStream<span class="o">)</span>
<span class="gp">0000000e  6e 10 07 00 03 00       invoke-virtual {v3}, int java.util.Scanner-&gt;</span>nextInt<span class="o">()</span>
<span class="go">00000014  0a 00                   move-result v0
00000016  00 00                   nop
00000018  00 00                   nop
0000001a  39 00 0a 00             if-nez v0, 10
BB-1e
</span><span class="gp">0000001e  62 01 01 00             sget-object v1, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="go">00000022  1a 02 12 00             const-string v2, "You gave me value 0..." (18)
</span><span class="gp">00000026  6e 20 03 00 21 00       invoke-virtual {v1, v2}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>java.lang.String<span class="o">)</span>
<span class="go">0000002c  28 08                   goto 60
BB-2e
</span><span class="gp">0000002e  62 01 01 00             sget-object v1, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="go">00000032  1a 02 0e 00             const-string v2, "Not a bad value :D..." (14)
</span><span class="gp">00000036  6e 20 03 00 21 00       invoke-virtual {v1, v2}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>java.lang.String<span class="o">)</span>
<span class="go">BB-3c (try block)
0000003c  12 31                   const/4 v1, 3
0000003e  b3 01                   div-int/2addr v1, v0
</span><span class="gp">00000040  62 00 01 00             sget-object v0, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="gp">00000044  6e 20 02 00 10 00       invoke-virtual {v0, v1}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>int<span class="o">)</span>
<span class="go">0000004a  28 09                   goto 92
BB-4c (catch block)
0000004c  0d 00                   move-exception v0
</span><span class="gp">0000004e  62 00 01 00             sget-object v0, Ljava/lang/System;</span>-&gt;out Ljava/io/PrintStream<span class="p">;</span> <span class="o">(</span>1<span class="o">)</span>
<span class="go">00000052  1a 01 01 00             const-string v1, "Divided by zero operation cannot possible" (1)
</span><span class="gp">00000056  6e 20 03 00 10 00       invoke-virtual {v0, v1}, void java.io.PrintStream-&gt;</span>println<span class="o">(</span>java.lang.String<span class="o">)</span>
<span class="go">BB-5c
</span><span class="gp">0000005c  6e 10 06 00 03 00       invoke-virtual {v3}, void java.util.Scanner-&gt;</span>close<span class="o">()</span>
<span class="go">00000062  0e 00                   return-void
BB-End Block
</span><span class="gp">Edges: BB-2e -&gt;</span><span class="w"> </span>BB-3c
<span class="gp">BB-4c -&gt;</span><span class="w"> </span>BB-5c
<span class="gp">BB-3c -&gt;</span><span class="w"> </span>BB-5c
<span class="gp">BB-1e -&gt;</span><span class="w"> </span>BB-3c
<span class="gp">BB-0 -&gt;</span><span class="w"> </span>BB-1e
<span class="gp">BB-0 -&gt;</span><span class="w"> </span>BB-2
</code></pre></div></div>

<p>As we can see in the previous output, this time the disassembler tells us about the basic blocks that belongs to this method. We have two empty nodes (start and end), and we also have two special basic blocks, one is the try block and the other the catch block.</p>

<p>Finally we will generate a <code class="language-plaintext highlighter-rouge">.dot</code> file, and we will convert it to a <code class="language-plaintext highlighter-rouge">.png</code>.</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>./dalvik-disassembler ../../kunai-lib/tests/test-try-catch/Main.dex <span class="s2">"LMain;"</span>  main <span class="nt">-p</span>
<span class="go">[2023-06-10 21:47:33.994] [stderr] [info] Analysis: correctly added parser to analysis object
</span><span class="gp">$</span><span class="w"> </span>dot <span class="nt">-Tpng</span> LMain<span class="se">\;</span>.main.dot <span class="nt">-o</span> main.png
</code></pre></div></div>

<p>The output is shown in the next image, this output shows the basic blocks as before, with their tags indicating if they are <code class="language-plaintext highlighter-rouge">start</code>, <code class="language-plaintext highlighter-rouge">end</code>, <code class="language-plaintext highlighter-rouge">try</code> or <code class="language-plaintext highlighter-rouge">catch</code> blocks. But also for the conditional jumps, the connections between the blocks will be painted on green (jump is taken) and red (jump is not taken, fallthrough), and unconditional jumps will be colored on blue.</p>

<figure>
<a href="/assets/images/kunai/main.png"><img src="/assets/images/kunai/main.png" /></a>
<figcaption>Control Flow Graph from disassembly output.</figcaption>
</figure>

<p>You can find all the code for this project in <a href="https://github.com/Fare9/KUNAI-static-analyzer/blob/refactoring/dalvik-disassembler/dalvik-disassembler.cpp">here</a></p>

<h2 id="last-words">Last words</h2>

<p>This long post tries to explain some basic usage from Kunai, Kunai is an ongoing project, so any help is always appreciated and welcome!</p>

<p>We hope you enjoyed the post, and also try using Kunai in one of your projects, you can contact us through the email of the project kunai.static.analysis(at)gmail(dot)com, if you use it in any of your projects, we will be happy to reference it in the repository.</p>

<p>See you in the next post!</p>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Android" /><category term="Analysis" /><category term="C++" /><category term="Dalvik" /><category term="Binary Analysis" /><category term="Android" /><summary type="html"><![CDATA[Kunai is a library for analyzing Dalvik Executable Files, this library is written in C++ for performance reasons]]></summary></entry><entry><title type="html">The Making of Fuzzing Against the Machine: A Chill Tale</title><link href="https://fare9.github.io/fuzzing/book/Fuzzing-Against-The-Machine/" rel="alternate" type="text/html" title="The Making of Fuzzing Against the Machine: A Chill Tale" /><published>2023-05-11T00:00:00+00:00</published><updated>2023-05-11T06:55:00+00:00</updated><id>https://fare9.github.io/fuzzing/book/Fuzzing-Against-The-Machine</id><content type="html" xml:base="https://fare9.github.io/fuzzing/book/Fuzzing-Against-The-Machine/"><![CDATA[<p>So, there we were, Christmas had just zoomed by, and life was kinda tough,
you know? We were all bummed about stuff that didn’t quite make sense such as Covid.
That’s when I hit up my buddy Eduardo on December 28th, 2021, a casual Tuesday, and
I was like, “Hey, dude, wanna help me write a book on something we can’t
totally wrap our heads around?” Eduardo was in the middle of his first year
of Ph.D. and feeling kinda lost too, so he was like, “Why not?”</p>

<p>We got together at our fave hangout spot, the COSEC lab at UC3M in Leganés,
near Madrid, and just started doodling ideas on the whiteboard. We knew there
was some cool stuff from the past few years about vulnerability discovery,
automation, and emulation that we could put together. But man, writing a book
is no joke—it takes forever! Even though we decided to use examples from the
community, we still had to dive deep into them at the bit level to make sure
we were giving our readers something worth their time.</p>

<p>And so, our epic adventure began. We laughed, we cried, and we geeked out as
we decoded the digital universe and turned it into a chill read for everyone
who was as curious as we were.</p>

<figure>
<a href="/assets/images/FuzzingATM/first_draft.jpeg"><img src="/assets/images/FuzzingATM/first_draft.jpeg" /></a>
<figcaption>The first draft of the first episode of the book.</figcaption>
</figure>

<h2 id="most-important-chapters-for-antonio">Most Important Chapters for Antonio</h2>

<h3 id="chapter-5-the-eluding-one">Chapter 5: The Eluding One</h3>

<p>During the summer of 2022, I had everything for the chapter on the VLC exploit
and patch ready to go. It was all saved on a microSD card from my Raspberry Pi.
But, like a total goof, I forgot to back it up, and when our reviewers came
back with notes, the card died, and I lost everything. I was so mad at myself,
but after redoing the whole thing, I realized the chapter needed even more work.
So, in a weird way, it was kinda a blessing in disguise.</p>

<h3 id="chapter-7-the-support-of-team-firmwire">Chapter 7: The Support of Team FirmWire</h3>

<p>I’ve been following Marius Muench and Grant Hernandez’s work on baseband since
2020, and I’ve also been in touch with Aurelienne and Davide from team Avatar.
When we reached out to them for a review of our chapters, they were super
helpful and stoked about our project. We can’t wait to gift some copies to
team FirmWire!</p>

<h3 id="chapter-10-ios">Chapter 10: iOS</h3>

<p>Trung Nguyen, the main dev behind this project, is a fantastic dude—always
down to help and offer advice. His work is seriously impressive, and we wanted
to give it some love by creating a rad PoC interface for fuzzing OS calls.
This chapter was tough, though—compiling Mach-O binaries on Linux was a
nightmare! We had to use a Mac for some stuff and find ways to help our readers
reproduce the exercises quickly.</p>

<p>Big thanks to everyone who helped, especially Eduardo. He taught me to approach
challenges with balance and thoughtfulness. I usually jump into things headfirst
and stress myself out, but this book was a great experience in learning how to
balance ambition, deadlines, and reality, all while juggling our day jobs.
Cheers, everyone!</p>

<h2 id="most-important-chapters-for-eduardo">Most Important Chapters for Eduardo</h2>

<h3 id="chapter-2-history-of-emulation">Chapter 2: History of Emulation</h3>

<p>While it would be easier to choose as important chapters any of the technical ones, I have decided to start as important (and also a list of favorite chapters), with chapter number 2 “History of Emulation”. This was one of those chapters that Antonio and I wrote during the first days of the book, we talked about all those times we spent playing around with famous emulators like <em>MAME</em> or these days with <em>RetroPie</em> (Operating System I have on my bartop Arcade Machine). We also reminded one bachelor thesis that talked about the process of writing an emulator. I think while not very technical, this chapter will make some people feel a little bit nostalgic about the past.</p>

<figure>
<a href="/assets/images/FuzzingATM/bartop.jpg"><img src="/assets/images/FuzzingATM/bartop.jpg" /></a>
<figcaption>Bartop Arcade Machine With a Raspberry and RetroPie.</figcaption>
</figure>

<h3 id="chapter-3-qemu-from-the-ground">Chapter 3: QEMU From the Ground</h3>

<p>This chapter introduces the reader into the world of QEMU, we were those days working at COSEC and digging into the documentation from QEMU (as well as the Airbus Seclab blog), and understanding how the emulation process was done on this tool. It is great understanding how QEMU works, since it applies a process of binary translation, based on its own Intermediate Representation and different methods for those instructions that do not have a direct translation into other architectures. This chapter will make the reader realize how powerful QEMU is.</p>

<h3 id="chapter-9-openwrt-system-fuzzing-for-arm">Chapter 9: OpenWrt System Fuzzing for ARM</h3>

<p>If I have to choose one chapter that I specially like and I remember writing is Chapter 9, a chapter that Antonio and I wrote while I was in Japan. Those days I was going to work to Qiqi’s university, while she had one of classes I was trying to setup all the docker images for running TriforceAFL for ARM. Here the reader will see how powerful is using QEMU+AFL, fuzzing system calls from a system that is (probably) different to the reader’s host machine.</p>

<p>I have to thank all those people who were there supporting me while doing this book. Of course, I have to thank Antonio for doing me join the crazy idea of writing a book about a topic I just had a small knowledge about, and allowed me to learn while writing. It was a long but nice journey. I hope you reader enjoy the book, as much as we did while writing it.</p>

<p><strong>See you space cowboy…</strong></p>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Fuzzing" /><category term="Book" /><category term="AFL" /><category term="AFL++" /><category term="QEMU" /><category term="Fuzzing" /><summary type="html"><![CDATA[History of how the idea of the book Fuzzing Against The Machine started and favorite chapters of the authors]]></summary></entry><entry><title type="html">Static Single Assignment Algorithm for MLIR</title><link href="https://fare9.github.io/compilers/mlir/ssa-mlir-algorithm/" rel="alternate" type="text/html" title="Static Single Assignment Algorithm for MLIR" /><published>2023-05-02T00:00:00+00:00</published><updated>2023-05-02T18:19:00+00:00</updated><id>https://fare9.github.io/compilers/mlir/ssa-mlir-algorithm</id><content type="html" xml:base="https://fare9.github.io/compilers/mlir/ssa-mlir-algorithm/"><![CDATA[<p>In this post we will talk about the algorithm used in Kunai for generating the SSA form in the Dialect created with MLIR for Dalvik Bytecode analysis, MjolnIR.</p>

<h2 id="authors">Authors</h2>

<ul>
  <li>Aymar Cublier</li>
  <li>Eduardo Blázquez</li>
</ul>

<h2 id="few-notes-on-static-single-assignment-ssa">Few notes on Static Single Assignment (SSA)</h2>

<p>As stated in <a href="https://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf">1</a>, SSA was conceived to make program analyses more efficient by compactly representing <em>use-def chains</em>. Since the main property of SSA form is that variables are defined just once, a definition is just a single point, so a definition can be stored as a pointer to an IR instruction. And uses of that value, can be defined as a list of pointers. In other case, we should keep track of where a variable is defined, since multiple definitions exist.</p>

<p>One of the first algorithms for generating SSA (and the first used on <em>Kunai</em> <a href="https://github.com/Fare9/KUNAI-static-analyzer/blob/refactoring/old/src/mjolnIR/Analysis/ir_graph_ssa.cpp">4</a>) was Cytron et al.’s algorithm, which guarantees a form of minimality on the number of <em>phi</em> function placed. The problem with this algorithm is that it relies on a program represented as a Control Flow Graph (CFG), and things like the dominance tree and dominance frontiers for placing the <em>phi</em> functions. After that, liveness analyses or dead code elimination are performed for removing unnecessary <em>phi</em> functions. So in that case we will have to follow the next step:</p>

<ol>
  <li>Representing input as a CFG.</li>
  <li>Computing Dominance Tree and Dominance frontiers.</li>
  <li>Placing Phi functions.</li>
  <li>Applying renaming of variables.</li>
</ol>

<p>In our case, the IR will be used for representing Dalvik Bytecode, and while we already have a disassembled bytecode in a CFG, it would be costly to compute the Dominance Tree and Dominance frontiers, also we want to directly emit IR based on MLIR. In the next sections we explore the algorithm used based in the algorithm given by <a href="https://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf">1</a> and the explanations from <a href="https://lowlevelbits.org/compiling-ruby-part-3/">3</a>.</p>

<h2 id="algorithm-explanation">Algorithm Explanation</h2>

<p>Since the MLIR framework does not consider <em>phi</em> instructions, MLIR blocks can have parameters. In case a value cannot be retrieved in a basic block (through <em>local value numbering</em>), we look for it in its predecessor blocks. We set the value we need in the block as <em>‘required for the block’</em>.</p>

<p>The value is searched in the block’s predecessor, but if the value we are looking for is not in the predecessor block either, we set that value for that predecessor as <em>‘required’</em> too, and in a recursive way that value will have to be searched in its own predecessors.</p>

<p>We then have two main functions: one is <em>readLocalVariable</em>, that looks for the Value in the current block applying the theory behind <em>local value numbering</em>, the other is <em>readLocalRecursiveVariable</em> and is used in the case we need to look for the Value in previous blocks,and then apply the <em>global value numbering</em> in the graph.</p>

<p><strong>Issue with MLIR</strong></p>

<p>The previous algorithm is very well explained in <a href="https://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf">1</a>, also we can find an explanation of <em>phi</em> functions placement in order to avoid infinite recursion. The main difference between the algorithm they explain, and the one we use is that in MLIR as explained at the beginning of this section, we do not have <em>phi</em> functions, we have basic block parameters, and its construction design needs from a previous analysis.
In the same way we add these values as <em>basic block parameters</em> in the block that <em>‘required’</em> the value, we will have to make the <em>terminator</em> instruction from a predecessor to <em>‘send’</em> as the value as one of its parameter. But while it is easy to add a parameter in a block, it is not that easy to add the parameters in the <em>terminal</em> instructions. Therefore, we need to apply the <em>Data Flow Analysis</em> before creating the <em>terminal</em> instructions.</p>

<p>We use a structure like the following one to keep track of the values during the <em>Data Flow Analysis</em>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">type</span> <span class="n">edge_t</span> <span class="o">=</span> <span class="n">pair</span><span class="o">&lt;</span><span class="n">BasicBlock</span><span class="p">,</span> <span class="n">BasicBlock</span><span class="o">&gt;</span><span class="p">;</span>

<span class="k">struct</span> <span class="nc">BasicBlockDef</span>
<span class="p">{</span>
    <span class="c1">/// Map a register to its definition in IR</span>
    <span class="n">Map</span><span class="o">&lt;</span><span class="n">reg</span><span class="p">,</span> <span class="n">Value</span><span class="o">&gt;</span> <span class="n">Defs</span><span class="p">;</span>
    <span class="c1">/// required values from the basic block</span>
    <span class="n">set</span><span class="o">&lt;</span><span class="n">reg</span><span class="o">&gt;</span> <span class="n">required</span><span class="p">;</span>
    <span class="c1">/// keep track of values that will be "send"</span>
    <span class="c1">/// to next basic blocks</span>
    <span class="n">Map</span><span class="o">&lt;</span><span class="n">edge_t</span><span class="p">,</span> <span class="n">Vector</span><span class="o">&lt;</span><span class="n">Value</span><span class="o">&gt;&gt;</span> <span class="n">jmpParameters</span><span class="p">;</span>    

    <span class="c1">/// Block is sealed, means no more predecessors will be</span>
    <span class="c1">/// added nor analyzed.</span>
    <span class="kt">bool</span> <span class="n">Analyzed</span><span class="p">;</span>

    <span class="n">BasicBlockDef</span><span class="p">()</span> <span class="o">:</span> <span class="n">Analyzed</span><span class="p">(</span><span class="n">False</span><span class="p">)</span> <span class="p">{}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>We additionally have a map like the following to keep this structure for each basic block:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Map&lt;BasicBlock, BasicBlockDef&gt; CurrentDef;
</code></pre></div></div>

<h3 id="data-flow-analysis">Data Flow Analysis</h3>

<p>Our algorithm first goes over each basic block, generating each instruction, but avoiding generating <em>terminal</em> instructions (e.g. jumps, conditional jumps, switch). During the generation of instructions, we apply the Data Flow Analysis.</p>

<p>Whenever we generate a new value, we apply <em>local value numbering</em> for keeping track of last value for each register used in a block. For doing that, we will have the next function (same function to the one presented at <a href="https://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf">1</a>):</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">writeLocalVariable</span><span class="p">(</span><span class="n">BB</span><span class="p">,</span> <span class="n">Reg</span><span class="p">,</span> <span class="n">Value</span><span class="p">)</span><span class="o">:</span>
    <span class="n">CurrentDef</span><span class="o">|</span><span class="n">BB</span><span class="o">|</span><span class="p">.</span><span class="n">Defs</span><span class="o">|</span><span class="n">Reg</span><span class="o">|</span> <span class="o">=</span> <span class="n">Val</span>
</code></pre></div></div>

<p>With this, we store the last value assigned for a register in a basic block. Now when a value is needed, we look for it first in the current block, and in case the value is not defined in this block, we look for it in its predecessor blocks.</p>

<p>In case we look for it in our block, we use the following function:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">readLocalVariable</span><span class="p">(</span><span class="n">BB</span><span class="p">,</span> <span class="n">Reg</span><span class="p">)</span><span class="o">:</span>
    <span class="n">Val</span> <span class="o">=</span> <span class="n">CurrentDef</span><span class="o">|</span><span class="n">BB</span><span class="o">|</span><span class="p">.</span><span class="n">Defs</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">Reg</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">Val</span><span class="o">:</span>
        <span class="k">return</span> <span class="n">Val</span>
    <span class="k">return</span> <span class="n">readLocalVariableRecursive</span><span class="p">(</span><span class="n">BB</span><span class="p">,</span> <span class="n">Reg</span><span class="p">)</span>
</code></pre></div></div>

<p>This function will try to obtain the definition of the value in the current block, but in case the value was not defined in the current block, we have to look for it in its predecessors, and for doing that we have the call to the function in the last line.</p>

<p>In order to look in the predecessors, we apply the following algorithm:</p>

<ul>
  <li>Insert the searched <em>Reg</em> into the list of <em>required</em> values in current block.</li>
  <li>Look for that <em>Reg</em> in the predecessor blocks of the current block</li>
  <li>As we are generating the SSA form at the moment, we have to check if the previous block was already analyzed (e.g. in a loop we could have the body was not analyzed yet). In case it was not, generate that block.</li>
  <li>Look for the value in the predecessor using <em>readLocalVariable</em>.</li>
  <li>Once the value is found, in case it is in the <em>required</em> list, add it as a parameter to the basic block and remove it from the <em>required</em> list.</li>
  <li>Keep track of the value for generating the <em>terminal</em> instructions after generating the CFG. In order to do that, keep the value in a map which key is an edge between <em>predecessor block</em> and <em>current block</em>.</li>
</ul>

<p>We can find the code in the following snippet:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">readLocalVariableRecursive</span><span class="p">(</span><span class="n">BB</span><span class="p">,</span> <span class="n">Reg</span><span class="p">)</span>
    <span class="n">new_value</span> <span class="o">:</span> <span class="n">Value</span>

    <span class="c1">/// add to Reg to required</span>
    <span class="n">CurrentDef</span><span class="o">|</span><span class="n">BB</span><span class="o">|</span><span class="p">.</span><span class="n">required</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">Reg</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">pred</span> <span class="n">in</span> <span class="n">predecessors</span><span class="p">(</span><span class="n">BB</span><span class="p">)</span><span class="o">:</span>
        <span class="k">if</span> <span class="n">not</span> <span class="n">CurrentDef</span><span class="o">|</span><span class="n">pred</span><span class="o">|</span><span class="p">.</span><span class="n">Analyzed</span><span class="o">:</span>
            <span class="n">gen_block</span><span class="p">(</span><span class="n">pred</span><span class="p">)</span>
        <span class="n">Val</span> <span class="o">=</span> <span class="n">readLocalVariable</span><span class="p">(</span><span class="n">pred</span><span class="p">,</span> <span class="n">Reg</span><span class="p">)</span>

        <span class="c1">/// If the value is required, add argument to the block</span>
        <span class="c1">/// write the local variable and erase from required</span>
        <span class="k">if</span> <span class="n">CurrentDef</span><span class="o">|</span><span class="n">BB</span><span class="o">|</span><span class="p">.</span><span class="n">required</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">Reg</span><span class="p">)</span><span class="o">:</span>
            <span class="c1">/// create value as argument in block</span>
            <span class="n">new_value</span> <span class="o">=</span> <span class="n">BB</span><span class="p">.</span><span class="n">addArgument</span><span class="p">(</span><span class="n">Val</span><span class="p">)</span>
            <span class="c1">/// write variable as local in basic block</span>
            <span class="n">writeLocalVariable</span><span class="p">(</span><span class="n">BB</span><span class="p">,</span> <span class="n">Reg</span><span class="p">,</span> <span class="n">new_value</span><span class="p">)</span>
            <span class="c1">/// remove from required</span>
            <span class="n">CurrentDef</span><span class="o">|</span><span class="n">BB</span><span class="o">|</span><span class="p">.</span><span class="n">required</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">Reg</span><span class="p">)</span>
        
        <span class="c1">/// now add the Value as a jump argument for later</span>
        <span class="c1">/// when we generate terminator instructions</span>
        <span class="n">CurrentDef</span><span class="o">|</span><span class="n">pred</span><span class="o">|</span><span class="p">.</span><span class="n">jmpParameters</span><span class="o">|&lt;</span><span class="n">pred</span><span class="p">,</span><span class="n">BB</span><span class="o">&gt;|</span><span class="p">.</span><span class="n">back</span><span class="p">(</span><span class="n">Val</span><span class="p">)</span>
    
    <span class="k">return</span> <span class="n">new_value</span>
</code></pre></div></div>

<p>Once we have finished generating the CFG, we can start generating the terminal instruction for each basic block, and because we have already cached the necessary parameters, we are able to generate the different terminal instructions with its parameters.</p>

<h3 id="representation">Representation</h3>

<p>For making easier to understand the problem and the algorithm, we have represented the cases in a few scenarios. We start with the simples case where we apply <em>local value numbering</em>, where we have a definition of a local value, and an instruction requiring using that same value in the same block (in the figures, the registers from the bytecode will be represented as <em>vX</em> and the values as <em>%X</em>, these values are not a one to one representation of the registers).</p>

<figure>
<a href="/assets/images/SSA_Algorithm/LocalValueNumbering.png"><img src="/assets/images/SSA_Algorithm/LocalValueNumbering.png" /></a>
<figcaption>Local Value Numbering.</figcaption>
</figure>

<p>In this case, the first instruction defined the value <em>%0</em> in the IR, and store it as a definition for <em>v0</em> register. The next instruction uses the register <em>v0</em>, so we need to look for the value defined for that register. Luckily in this case, the value has been previously defined in the same block, so calling to <em>readLocalVariable</em>, we obtain the defined value.</p>

<p>The next case is the simplest case of <em>global value numbering</em>, in the case we only have one predecessor, and the value we need was previously defined by that predecessor:</p>

<figure>
<a href="/assets/images/SSA_Algorithm/GlobalValueNumbering1.png"><img src="/assets/images/SSA_Algorithm/GlobalValueNumbering1.png" /></a>
<figcaption>Global Value Numbering Simple Case.</figcaption>
</figure>

<p>In this case, when the algorithm tries to obtain the definition of the needed value in the current basic block it fails, and have to call to <em>readLocalVariableRecursive</em>. In this case, we find that the value was defined in the previous block, then it is possible to create the parameter and assign it to the instruction, and record the value for the moment when we generate the terminal instructions, that will be once we have transformed all basic blocks to our MLIR Dialect.</p>

<p>Now we will see a more complicated case. In this case, our immediate predecessor has not defined the required value, so it will have to look for the value on its own predecessor, this value will have to be propagated through basic block parameters and through terminal instructions.</p>

<figure>
<a href="/assets/images/SSA_Algorithm/GlobalValueNumbering2.png"><img src="/assets/images/SSA_Algorithm/GlobalValueNumbering2.png" /></a>
<figcaption>Global Value Numbering Complicated Case.</figcaption>
</figure>

<p>The process is similar to the simplest case, but because the value is not found in the predecessor, the predecessor block will have to set the Reg as <em>‘required’</em>, and look for its value on its predecessor. Once we find it, the recursion stops and the algorithm starts propagating the value through the block parameters, and keeping track of them for later generating the terminal instructions.</p>

<p>The next two figures represent two use cases, one is an <em>if-else</em> example where we can see that since the algorithm looks for the value in all the predecessors from a basic block, in the predecessor where the value is not defined, this will have to be propagated from previous basic blocks, allowing to retrieve all the possible previous values.</p>

<figure>
<a href="/assets/images/SSA_Algorithm/Example-if-else.png"><img src="/assets/images/SSA_Algorithm/Example-if-else.png" /></a>
<figcaption>If-Else Example.</figcaption>
</figure>

<p>The other example we find is the next, a <em>loop</em> where we could find that the <em>body</em> of the <em>loop</em> requires a value that was not defined by the predecessor. In this case, the predecessor (<em>BB1</em> in this case) will look for the value first on <em>BB0</em>, since looking for the value in its other predecessor (<em>BB2</em>) would create an infinite recursion problem. Since the value is propagated and created as a basic block parameter in <em>BB1</em>, <em>BB2</em> will obtain a correct value and infinite recursion is stopped here.</p>

<figure>
<a href="/assets/images/SSA_Algorithm/ExampleLoop.png"><img src="/assets/images/SSA_Algorithm/ExampleLoop.png" /></a>
<figcaption>Loop Example.</figcaption>
</figure>

<h2 id="clarification">Clarification</h2>

<p>We will like to clarify that in this case, the algorithm is not applied to a source code, but to a disassembled code from Dalvik Bytecode, so we do not have access to things like <em>loop headers</em> or <em>loop bodies</em>, nor similar structures. All we access is a CFG from the disassembled output from Dalvik bytecode.</p>

<p>You can find all the code of the algorithm at <a href="https://github.com/Fare9/KUNAI-static-analyzer/blob/refactoring/kunai-lib/MjolnIR/include/Lifter/MjolnIRLifter.hpp">5</a> and <a href="https://github.com/Fare9/KUNAI-static-analyzer/tree/refactoring/kunai-lib/MjolnIR/lib/Lifter">6</a>.</p>

<h2 id="acknowledgments">Acknowledgments</h2>

<p>We would like to thank Alex Denisov for his explanation about the algorithm used at <a href="https://lowlevelbits.org/compiling-ruby-part-3/">3</a>, that were really useful for writing the one used in Kunai. Also MLIR community for helping us with few comments on compilation errors on our MLIR Dialect.</p>

<h2 id="references">References</h2>

<ul>
  <li>1: Simple and Efficient Construction of Static Single Assignment Form</li>
  <li>2: Value Numbering</li>
  <li>3: Compiling Ruby. Part 3: MLIR and compilation</li>
  <li>4: Cytron Algorithm Kunai</li>
  <li>5: MjolnIR Lifter header</li>
  <li>6: MjolnIR Lifter source code</li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;&quot;/assets/images/fare9.jpg&quot;, &quot;bio&quot;=&gt;&quot;Compiler Engineer at Quarkslab&quot;, &quot;location&quot;=&gt;&quot;Madrid, Spain&quot;, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Twitter&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-twitter-square&quot;, &quot;url&quot;=&gt;&quot;https://twitter.com/Farenain&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/Fare9&quot;}]}</name></author><category term="Compilers" /><category term="MLIR" /><category term="C++" /><category term="Compilers" /><category term="MLIR" /><category term="LLVM" /><category term="SSA" /><category term="Algorithm" /><category term="Dalvik" /><summary type="html"><![CDATA[Explanation of Static Single Assignment Algorithm for MLIR]]></summary></entry></feed>