Advertisement
elvanderb

0vercl0k chall """solution"""

Sep 18th, 2013
1,079
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.53 KB | None | 0 0
  1. # ugly poc written for 0vercl0k[] chall
  2. # hardcoded addresses, slow, but you'll have the idea :)
  3. # IL + data tainting + symbolic execution + some trickz
  4. # it could be a lot faster/cleaner but I don't have time to work on it, it was just a fast PoC
  5. # thks to 0vercl0k for taking the time to write a clean writeup ;)
  6. # -> http://doar-e.github.io/blog/2013/09/16/breaking-kryptonites-obfuscation-with-symbolic-execution/
  7.  
  8. import sys
  9. sys.path.append("C:\\Program Files (x86)\\z3-4.3.0-x86\\bin")
  10. from idc import *
  11. from collections import defaultdict
  12. from z3 import *
  13. from pprint import pprint
  14. import re
  15. import PySide
  16. from PySide.QtGui import QMessageBox
  17.  
  18. addr_check = 0x140F19996
  19.  
  20. class BVRegs(dict) :
  21.     def __init__(self) :
  22.         dict.__init__(self, {r:BitVec(r, 64) for r in Reg.regs})
  23.  
  24.     def __setitem__(self, item, value) :
  25.         dict.__setitem__(self, item, simplify(value))
  26.  
  27.     def __str__(self) :
  28.         return "\n".join("%s : %s"%(r,self[r]) for r in Reg.regs)
  29.  
  30. class BVContext(object) :
  31.     def __init__(self) :
  32.         self.sym_count = 0
  33.         self.regs = BVRegs()
  34.         self.memory = {}
  35.         self.used_addr = set()
  36.  
  37.     def deref_read(self, addr) :
  38.         # fucking ugly but works ... just consider that != str => != addr
  39.         return self.memory.setdefault(str(addr), BitVec("[%s]"%addr, 64))
  40.  
  41.     def deref_write(self, addr, value) :
  42.         self.memory[str(addr)] = simplify(value)
  43.  
  44.     def int2abstract(self, i) :
  45.         return BitVecVal(i, 64)
  46.  
  47.     def __getitem__(self, item) :
  48.         if isinstance(item, Expr) :
  49.             return item.get_value(self)
  50.         elif isinstance(item, int) or isinstance(item, long) :
  51.             return BitVecVal(item, 64)
  52.         raise Exception("invalid item :\n\t%r"%item)
  53.  
  54.     def __setitem__(self, item, value) :
  55.         if isinstance(item, Expr) :
  56.             return item.set_value(self, value)
  57.         raise Exception("invalid item :\n\t%r"%item)
  58.  
  59.     def __str__(self) :
  60.         ret_val = "%s\n"%self.regs
  61.         mem = ["%s : %s"%(r,v) for r,v in self.memory.items()]
  62.         mem.sort()
  63.         ret_val += "\n".join(mem)
  64.         return ret_val
  65.  
  66. class Singleton(type):
  67.     def __init__(self, *args, **kwargs):
  68.         super(Singleton, self).__init__(*args, **kwargs)
  69.         self.__instances = {}
  70.  
  71.     def __call__(self, *args, **kwargs):
  72.         arg = args[0] if len(args) else None
  73.         return self.__instances.setdefault(arg, super(Singleton, self).__call__(*args, **kwargs))
  74.  
  75. class Taint(frozenset) :
  76.     __metaclass__ = Singleton
  77.  
  78.     def __init__(self, taints=None) :
  79.         if taints :
  80.             if len(taints) > 1 :
  81.                 raise DecodeException("toto")
  82.             frozenset.__init__(self, taints)
  83.         else :
  84.             frozenset.__init__(self)
  85.  
  86.     def __add__(self, b) :
  87.         return Taint(self.union(b))
  88.  
  89.     def __sub__(self, b) :
  90.         return Taint(self.union(b))
  91.  
  92.     def __and__(self, b) :
  93.         return Taint(self.union(b))
  94.  
  95.     def __or__(self, b) :
  96.         return Taint(self.union(b))
  97.  
  98.     def __xor__(self, b) :
  99.         return Taint(self.union(b))
  100.  
  101.     def __neg__(self) :
  102.         return self
  103.  
  104.     def __invert__(self) :
  105.         return self
  106.  
  107.     def __lshift__(self, b) :
  108.         return Taint(self.union(b))
  109.  
  110.     def __rshift__(self, b) :
  111.         return Taint(self.union(b))
  112.  
  113.     def __str__(self)  :
  114.         return ", ".join(self)
  115.  
  116. class TaintedRegs(dict) :
  117.     def __init__(self) :
  118.         dict.__init__(self, {r:Taint(frozenset((r,))) for r in Reg.regs})
  119.  
  120.     def __str__(self) :
  121.         return "\n".join("%s : %s"%(r,self[r]) for r in Reg.regs)
  122.  
  123. class TaintedContext(object) :
  124.     def __init__(self) :
  125.         self.sym_count = 0
  126.         self.regs = TaintedRegs()
  127.         self.memory = {}
  128.         self.used_addr = set()
  129.  
  130.     def deref_read(self, addr) :
  131.         # fucking ugly but works ... just consider that != str => != addr
  132.         v = self.memory.setdefault(str(addr), Taint(frozenset(("[%s]"%addr,))))
  133.         return v
  134.  
  135.     def deref_write(self, addr, value) :
  136.         self.memory[str(addr)] = value
  137.  
  138.     def int2abstract(self, i) :
  139.         return Taint()
  140.  
  141.     def __getitem__(self, item) :
  142.         if isinstance(item, Expr) :
  143.             return item.get_value(self)
  144.         elif isinstance(item, int) or isinstance(item, long) :
  145.             return Taint()
  146.         raise Exception("invalid item :\n\t%r"%item)
  147.  
  148.     def __setitem__(self, item, value) :
  149.         if isinstance(item, Expr) :
  150.             return item.set_value(self, value)
  151.         raise Exception("invalid item :\n\t%r"%item)
  152.  
  153.  
  154.     def __str__(self) :
  155.         ret_val = "%s\n"%self.regs
  156.         mem = ["%s : %s"%(r,v) for r,v in self.memory.items()]
  157.         mem.sort()
  158.         ret_val += "\n".join(mem)
  159.         return ret_val
  160.  
  161. class Mix(object) :
  162.     def __init__(self, bv, taint) :
  163.         self.bv = bv
  164.         self.taint = taint
  165.  
  166.     @staticmethod
  167.     def wrapp(name):
  168.         bv_attr = getattr(BitVecRef, name)
  169.         taint_attr = getattr(Taint, name)
  170.         if hasattr(bv_attr, '__call__') and hasattr(taint_attr, '__call__') :
  171.             def newfunc(*args):
  172.                 bv_args = tuple(arg.bv for arg in args)
  173.                 taint_args = tuple(arg.taint for arg in args)
  174.                 result = Mix(bv_attr(*bv_args), taint_attr(*taint_args))
  175.                 return result
  176.             return newfunc
  177.         raise Exception("unkown attribute")
  178.  
  179.     def __str__(self) :
  180.         return "\tbv: %s\n\ttaint: %s"%(self.bv, self.taint)
  181.  
  182. for n in ("add", "sub", "and", "or", "xor", "neg", "invert", "lshift", "rshift") :
  183.     setattr(Mix, "__%s__"%n, Mix.wrapp("__%s__"%n))
  184.  
  185. class MixedRegs(object) :
  186.  
  187.     def __init__(self, mixedContext) :
  188.         self.bv_regs = mixedContext.bv_ctx.regs
  189.         self.tainted_regs = mixedContext.tainted_ctx.regs
  190.  
  191.     def __getitem__(self, item) :
  192.         return Mix(self.bv_regs[item],
  193.                 self.tainted_regs[item])
  194.  
  195.     def __setitem__(self, item, value) :
  196.         self.bv_regs[item] = value.bv
  197.         self.tainted_regs[item] = value.taint
  198.  
  199.  
  200.     def __str__(self) :
  201.         return "\n".join("%s : %s"%(r, self[r]) for r in Reg.regs)
  202.  
  203. class MixedContext(object) :
  204.  
  205.     def __init__(self) :
  206.         self.bv_ctx = BVContext()
  207.         self.tainted_ctx = TaintedContext()
  208.         self.regs = MixedRegs(self)
  209.  
  210.     def deref_read(self, addr) :
  211.         # use bv address
  212.         return Mix(self.bv_ctx.deref_read(addr.bv), self.tainted_ctx.deref_read(addr.bv))
  213.  
  214.     def deref_write(self, addr, value) :
  215.         self.bv_ctx.deref_write(addr.bv, value.bv)
  216.         self.tainted_ctx.deref_write(addr.bv, value.taint)
  217.  
  218.     def int2abstract(self, i) :
  219.         return Mix(self.bv_ctx.int2abstract(i),
  220.                 self.tainted_ctx.int2abstract(i))
  221.  
  222.     def __getitem__(self, item) :
  223.         if isinstance(item, Expr) :
  224.             return item.get_value(self)
  225.         elif isinstance(item, int) or isinstance(item, long) :
  226.             return self.int2abstract(item)
  227.         raise Exception("invalid item :\n\t%r"%item)
  228.  
  229.     def __setitem__(self, item, value) :
  230.         if isinstance(item, Expr) :
  231.             return item.set_value(self, value)
  232.         raise Exception("invalid item :\n\t%r"%item)
  233.  
  234.     def __str__(self) :
  235.         ret_val = "%s\n"%self.regs
  236.         mem = ["%s :\n\tbv: %s\n\ttaint: %s)"%(r,v,self.tainted_ctx.memory[r]) for r,v in self.bv_ctx.memory.items()]
  237.         mem.sort()
  238.         ret_val += "\n".join(mem)
  239.         return ret_val
  240.  
  241.  
  242. class Expr(object) :
  243.     size = None
  244.     funs = {
  245.         "+" : (lambda x, y : x + y),
  246.         "-" : (lambda x, y : x - y),
  247.         "&" : (lambda x, y : x & y),
  248.         "|" : (lambda x, y : x | y),
  249.         "^" : (lambda x, y : x ^ y),
  250.         "<<" : (lambda x, y : x << y),
  251.         ">>" : (lambda x, y : x >> y),
  252.         "u-" : (lambda x : -x),
  253.         "~" : (lambda x : ~y),
  254.     }
  255.     def __init__(self, operator, *operands) :
  256.         self.opr = str(operator)
  257.         self.ops = operands
  258.         self.fun = Expr.funs[self.opr]
  259.  
  260.         if len(self.ops) > 1 :
  261.             self._str = self.opr.join("%s"%op if isinstance(op, Operand) else "(%s)"%op for op in self.ops)
  262.         else :
  263.             op = self.ops[0]
  264.             self._str = self.opr + ("%s"%op if isinstance(op, Operand) else "(%s)"%op)
  265.  
  266.     def __str__(self) :
  267.         return self._str
  268.  
  269.     def __add__(self, b) :
  270.         return Expr("+", self, b)
  271.  
  272.     def __sub__(self, b) :
  273.         return Expr("-", self, b)
  274.  
  275.     def __and__(self, b) :
  276.         return Expr("&", self, b)
  277.  
  278.     def __or__(self, b) :
  279.         return Expr("|", self, b)
  280.  
  281.     def __xor__(self, b) :
  282.         return Expr("^", self, b)
  283.  
  284.     def __neg__(self) :
  285.         return Expr("u-", self)
  286.  
  287.     def __invert__(self) :
  288.         return Expr("~", self)
  289.  
  290.     def __lshift__(self, b) :
  291.         return Expr("<<", self, b)
  292.  
  293.     def __rshift__(self, b) :
  294.         return Expr(">>", self, b)
  295.  
  296.     def get_value(self, context) :
  297.         return self.fun(*tuple(op.get_value(context) for op in self.ops))
  298.  
  299. class Operand(Expr) :
  300.     pass
  301.  
  302. class Reg(Operand) :
  303.     regs = []
  304.     _str_to_rms = {}
  305.     for s in ("a", "b", "c", "d") :
  306.         r = "r" + s + "x"
  307.         regs.append(r)
  308.         _str_to_rms[s+"l"] = (r, 0xFF, 0, 1)
  309.         _str_to_rms[s+"h"] = (r, 0xFF00, 8, 1)
  310.         _str_to_rms[s+"x"] = (r, 0xFFFF, 0, 2)
  311.         _str_to_rms["e"+s+"x"] = (r, 0xFFFFFFFF, 0, 4)
  312.         _str_to_rms["r"+s+"x"] = (r, 0xFFFFFFFFFFFFFFFF, 0, 8)
  313.  
  314.     for s in ("di", "si", "sp", "bp") :
  315.         r = "r" + s
  316.         regs.append(r)
  317.         _str_to_rms[s+"l"] = (r, 0xFF, 0, 1)
  318.         _str_to_rms[s] = (r, 0xFFFF, 0, 2)
  319.         _str_to_rms["e"+s] = (r, 0xFFFFFFFF, 0, 4)
  320.         _str_to_rms["r"+s] = (r, 0xFFFFFFFFFFFFFFFF, 0, 8)
  321.  
  322.     for s in xrange(8, 16) :
  323.         s = "r%d"%s
  324.         regs.append(s)
  325.         _str_to_rms[s+"b"] = (s, 0xFF, 0, 1)
  326.         _str_to_rms[s+"w"] = (s, 0xFFFF, 0, 2)
  327.         _str_to_rms[s+"d"] = (s, 0xFFFFFFFF, 0, 4)
  328.         _str_to_rms[s] = (s, 0xFFFFFFFFFFFFFFFF, 0, 8)
  329.     regs = tuple(regs)
  330.  
  331.     def __init__(self, s) :
  332.         self._str = str(s)
  333.         self.reg, self.mask, self.shift, self.size = Reg._str_to_rms[self._str]
  334.  
  335.     def __str__(self) :
  336.         return self._str
  337.  
  338.     def get_value(self, context) :
  339.         v = context.regs[self.reg]
  340.         if self.mask != 0xFFFFFFFFFFFFFFFF :
  341.             v &= context[self.mask]
  342.         if self.shift != 0 :
  343.             v >>= context[self.shift]
  344.         return v
  345.  
  346.     def set_value(self, context, value) :
  347.         if self.mask >= 0xFFFFFFFF :
  348.             context.regs[self.reg] = value
  349.             return
  350.         if self.shift != 0 :
  351.             value <<= self.shift
  352.         context.regs[self.reg] = (context.regs[self.reg] & ~context[self.mask]) | value
  353.  
  354. class Mem(Operand) :
  355.     magic_regex = re.compile(r'\[((?P<base>([abcdspirexhl]{1,3}[0-9]{0,2}(?!\*)))?(((?P<index_sign>[+-]))?(?P<index>[abcdspirexhl]{1,3}[0-9]{0,2})(\*(?P<index_mult>[2-8]))?)?((?P<disp>[+-][0-9A-F]+)h?)?|((?P<addr>-?[0-9A-F])+h?))\]')
  356.    
  357.     def __init__(self, expr) :
  358.         self.expr = expr
  359.         self._str = "[%s]"%expr
  360.  
  361.     def __str__(self) :
  362.         return self._str
  363.  
  364.     @staticmethod
  365.     def str2mem(s) :
  366.         s = str(s)
  367.         try :
  368.             base, index_sign, index, _index_mult, _disp, addr = Mem.magic_regex.match(s).group("base", "index_sign", "index", "index_mult", "disp", "addr")
  369.         except :
  370.             raise Exception("Unkown memory address : %s"%s)
  371.         exp = None
  372.         if _disp :
  373.             _disp = int(_disp, 16)
  374.             if _disp :
  375.                 exp = Cst(_disp)
  376.         if addr :
  377.             exp = Cst(int(addr, 16))
  378.         index_mult = None
  379.         if index_mult :
  380.             _index_mult = int(_index_mult)
  381.             if _index_mult != 1 :
  382.                 index_mult = _index_mult
  383.  
  384.         if base :
  385.             base = Reg(base)
  386.             exp = base + exp if exp is not None else base
  387.         if index :
  388.             index = Reg(index)
  389.             if index_mult :
  390.                 index = index * Cst(index_mult)
  391.             if index_sign == "-" :
  392.                 index = -index
  393.             exp = index + exp if exp is not None else index
  394.         return Mem(exp)
  395.  
  396.     def get_value(self, context) :
  397.         addr = self.expr.get_value(context)
  398.         return context.deref_read(addr)
  399.  
  400.     def set_value(self, context, value) :
  401.         addr = context[self.expr]
  402.         return context.deref_write(addr, value)
  403.  
  404. class Cst(Operand) :
  405.  
  406.     def __init__(self, v) :
  407.         self._str = "0x%08X"%v
  408.         self.v = int(v)
  409.         self._size = None
  410.    
  411.     @property
  412.     def size(self):
  413.         return self._size
  414.  
  415.     @size.setter
  416.     def size(self, value):
  417.         assert (1 << (value*8)) > abs(self.v)
  418.         self._size = value
  419.    
  420.     def get_value(self, context) :
  421.         return context[self.v]
  422.  
  423.     def __str__(self) :
  424.         return self._str
  425.  
  426. def normalize_sizes(*operands) :
  427.     '''set operand size so every sizes are equals, if there is any non matching size : raise Exc'''
  428.     for op in operands :
  429.         if op.size :
  430.             size = op.size
  431.             break
  432.     else :
  433.         raise Exception("no known size")
  434.  
  435.     if any(op.size != size for op in operands if op.size is not None) :
  436.         raise Exception("sizes are not matching")
  437.  
  438.     for op in operands :
  439.         op.size = size
  440.  
  441. def get_op(addr, i) :
  442.     inst = GetOpType(addr, i)
  443.     if inst < 1 :
  444.         return None
  445.     elif inst == 1 : # reg
  446.         return Reg(GetOpnd(addr, i))
  447.     elif 2 <= inst <= 4 :
  448.         return Mem.str2mem(GetOpnd(addr, i))
  449.     elif 5 <= inst <= 7 :
  450.         return Cst(GetOperandValue(addr, i))
  451.     else :
  452.         raise Exception("unkown operand (%X %d)"%(addr, i))
  453.  
  454. ins2mc_funs = {}
  455. def ins2mc_add(dst, src) :
  456.     normalize_sizes(dst, src)
  457.     return [(dst, dst + src)]
  458. ins2mc_funs["add"] = ins2mc_add
  459.  
  460. def ins2mc_and(dst, src) :
  461.     normalize_sizes(dst, src)
  462.     return [(dst, dst & src)]
  463. ins2mc_funs["and"] = ins2mc_and
  464.  
  465. def ins2mc_shr(dst, src) :
  466.     return [(dst, dst >> src)]
  467. ins2mc_funs["shr"] = ins2mc_shr
  468.  
  469. def ins2mc_shl(dst, src) :
  470.     return [(dst, dst << src)]
  471. ins2mc_funs["shl"] = ins2mc_shl
  472.  
  473. def ins2mc_xor(dst, src) :
  474.     normalize_sizes(dst, src)
  475.     return [(dst, dst ^ src)]
  476. ins2mc_funs["xor"] = ins2mc_xor
  477.  
  478. def ins2mc_or(dst, src) :
  479.     normalize_sizes(dst, src)
  480.     return [(dst, dst | src)]
  481. ins2mc_funs["or"] = ins2mc_or
  482.  
  483. def ins2mc_mov(dst, src) :
  484.     normalize_sizes(dst, src)
  485.     return [(dst, src)]
  486. ins2mc_funs["mov"] = ins2mc_mov
  487.  
  488.  
  489. class DecodeException(Exception) :
  490.     pass
  491.  
  492. def ins2mc(addr) :
  493.     mnem = GetMnem(addr)
  494.     if mnem == "" :
  495.         raise DecodeException("Unkown instruction @ %X"%(mnem, addr))
  496.     ops = [op for op in [get_op(addr, i) for i in xrange(3)] if op]
  497.     if mnem not in ins2mc_funs :
  498.         raise DecodeException("Unkown instruction %s @ %X"%(mnem, addr))
  499.     return ins2mc_funs[mnem](*ops)
  500.  
  501.  
  502. def simplify_linear(v, symbol) :
  503.     s = Solver()
  504.  
  505.     a = simplify(substitute(v, (BitVec(symbol, 64), BitVecVal(0, 64))))
  506.     s.add(a + BitVec(symbol, 64)  & 0xFFFFFFFF != v & 0xFFFFFFFF)
  507.     print a
  508.     print s.check()
  509.     if s.check() == unsat :
  510.         return a + BitVec(symbol, 64)
  511.     print s.model()
  512.     return v
  513.  
  514.  
  515. eip = 0x00140F199E9
  516. prev = eip
  517. context = MixedContext()
  518.  
  519. msgBox = QMessageBox()
  520. msgBox.setText("Break")
  521. msgBox.setInformativeText("Break")
  522. msgBox.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok | QMessageBox.Close)
  523. msgBox.setDefaultButton(QMessageBox.Ok)
  524. stepinto = False
  525. try :
  526.     while True :
  527.         if eip == 0x0140F1BD06   :
  528.             stepinto = True
  529.         if stepinto :
  530.             # print context.bv_ctx
  531.             # print context.tainted_ctx
  532.             # print context
  533.             syms = set(context.tainted_ctx.regs["rdi"])
  534.             sym = syms.pop()
  535.             print context.tainted_ctx.regs["rdi"]
  536.             print simplify_linear(context.bv_ctx.regs["rdi"], sym)
  537.             ret = msgBox.exec_()
  538.             if ret == QMessageBox.Cancel:
  539.                 sys.exit()
  540.             if ret == QMessageBox.Close :
  541.                 stepinto = False
  542.         for dst, expr in ins2mc(eip) :
  543.             v = context[expr]
  544.             # if len(v.taint) > 1 :
  545.             #   print hex(eip)
  546.             #   print "bv:", str(simplify(v.bv))
  547.             #   print "taint:", str(v.taint)
  548.             #   stepinto = True
  549.             context[dst] = v
  550.         eip += ItemSize(eip)
  551.         if eip - prev >= 0x1000 :
  552.             print hex(eip)
  553.             prev = eip
  554. except DecodeException as e :
  555.     pass
  556.  
  557. print "prout"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement