Write-ups DefCamp 2015 – r100 with triton

We were given a binary (downloadable from github).

 

Let’s run it:

$ ./r100.bin 
Enter the password: AAAAAA
Incorrect password!

 

We want to check the source code in IDA:

Screen Shot 2015-10-14 at 10.40.06

 

It doesn’t look really complicated but it is a perfect opportunity to have fun with Triton!

To use Triton we need to know two things:

  1. What is my X in the equation? (Obviously it is the input here…)
  2. Where should I need to solve the equation?

So let’s check the disassembly code for that. Below is the loop, where “pass” is our input.

Screen Shot 2015-10-14 at 10.34.57

We can see that our X will be at 0x400781 (RAX value right after the instruction).

Then we want to solve the equation at 0x40078b (you can do it before too, it’s not a static choice…)

So we will use the snapshot features of python to do the following steps:

  1. At 0x40072d (beginning of the loop) : Take a snapshot so we can come back here later and set i value
  2. At 0x400781 : Set RAX as my X in the equation
  3. At 0x40078b: Resolve my equation with Z3. If i < 12, restore the snapshot and increment i. Restoring the snapshot take us back to point 1)

Translating that into python with Triton:

from triton import *

import smt2lib
import os, sys
from elftools.elf.elffile import ELFFile

FILENAME = 'r100'

password  = ""
i=0

def callbackBefore(instruction):
    global password

    global i
    if instruction.getAddress()==0x40072d and isSnapshotEnabled()==False:
        print "[+] Take Snapshot"
        takeSnapshot()
    if instruction.getAddress()==0x40072d:
        setMemValue(instruction.getOperands()[1].getMem().getAddress(),1,i)
    if instruction.getAddress()==0x4007a7:
        print "[+]Password: %s" %(password)


def syscallEntry(instruction):
    global i
    global password

    if instruction.getAddress()==0x400781:
        convertRegToSymVar(IDREF.REG.RAX,64)


    if instruction.getAddress()==0x40078b:
        operandR = instruction.getOperands()[1]
        operandL = instruction.getOperands()[0]
        equalTo = 0x00
        equalTo=operandR.getImm().getValue()

        symbolicId = getRegSymbolicID(operandL.getReg().getId())
        raxExpr = getFullExpression(getSymExpr(symbolicId).getAst())
        conditions =  list()
        conditions.append( smt2lib.smtAssert(smt2lib.equal(raxExpr, smt2lib.bv(equalTo, 64))))
        expr = smt2lib.compound(conditions)

        model = getModel(expr)
        print {k: "0x%x, '%c'" % (v, chr(int(str(hex(v)).rstrip("0"),16))) for k, v in model.items()
}
        for k, v in model.items():
            c = chr(int(str(hex(v)).rstrip("0"),16))
            print "[+] Adding %c to password" %(c)
            password += c
            i += 1
            if i<12:
                print "[+] Restore snapshot"
                restoreSnapshot()


if __name__ == '__main__':
    with open(FILENAME, 'rb') as f:
        elffile = ELFFile(f)
        header = elffile.header

    # Start the symbolic analysis from the entry point
    startAnalysisFromAddr(header["e_entry"])

    # Add a callback.
    addCallback(syscallEntry, IDREF.CALLBACK.AFTER)
    addCallback(callbackBefore, IDREF.CALLBACK.BEFORE)

    # Run the instrumentation - Never returns
    runProgram()

Let’s run it. One detail, we didn’t set a static value for our input so we need to manually give an input of at least 11 chars:

 

$ echo "11111111111111"|triton r100.blog.py ./r100
[+] Take Snapshot
{'SymVar_0': "0x43, 'C'"}
[+] Adding C to password
[+] Restore snapshot
{'SymVar_0': "0x6f, 'o'"}
[+] Adding o to password
[+] Restore snapshot
{'SymVar_0': "0x64, 'd'"}
[+] Adding d to password
[+] Restore snapshot
{'SymVar_0': "0x65, 'e'"}
[+] Adding e to password
[+] Restore snapshot
{'SymVar_0': "0x5f, '_'"}
[+] Adding _ to password
[+] Restore snapshot
{'SymVar_0': "0x54, 'T'"}
[+] Adding T to password
[+] Restore snapshot
{'SymVar_0': "0x61, 'a'"}
[+] Adding a to password
[+] Restore snapshot
{'SymVar_0': "0x6c, 'l'"}
[+] Adding l to password
[+] Restore snapshot
{'SymVar_0': "0x6b, 'k'"}
[+] Adding k to password
[+] Restore snapshot
{'SymVar_0': "0x65, 'e'"}
[+] Adding e to password
[+] Restore snapshot
{'SymVar_0': "0x72, 'r'"}
[+] Adding r to password
[+] Restore snapshot
{'SymVar_0': "0x73, 's'"}
[+] Adding s to password
[+]Password: Code_Talkers
Enter the password: Incorrect password!

$ echo "Code_Talkers" | ./r100
Enter the password: Nice!

We could do the script more specific and more “automatic” with the taint system of triton.

I will try to do that in another write-ups.

Leave a Reply

Your email address will not be published. Required fields are marked *