Advertisement
REURES

Untitled

Dec 5th, 2014
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.37 KB | None | 0 0
  1. import re
  2. from idc import GetMnem, GetOpnd, GetOpType, SetColor, ItemSize, PrevHead, CIC_ITEM, GetDisasm
  3. from random import randint
  4.  
  5. code = '''
  6. def _sub(a, b):
  7.    return (a - b) & 0xFFFFFFFF
  8.  
  9. def _add(a, b):
  10.    return (a + b) & 0xFFFFFFFF
  11.  
  12. def _rol(a, b):
  13.    return ((a << (b & 0x1F)) | (a >> (32 - (b & 0x1F)))) & 0xFFFFFFFF
  14.  
  15. def _ror(a, b):
  16.    return _rol(a, 32 - (b & 0x1F))
  17.  
  18. def _shr(a, b):
  19.    return (a >> b) & 0xFFFFFFFF
  20.  
  21. def _shl(a, b):
  22.    return (a << b) & 0xFFFFFFFF
  23.  
  24. def _xor(a, b):
  25.    return (a ^ b) & 0xFFFFFFFF
  26.  
  27. def _and(a, b):
  28.    return (a & b) & 0xFFFFFFFF
  29.  
  30. def _or(a, b):
  31.    return (a | b) & 0xFFFFFFFF
  32.  
  33. def _imul(a, b):
  34.    return (a * b) & 0xFFFFFFFF
  35.  
  36. def _neg(a):
  37.    return (-a) & 0xFFFFFFFF
  38.  
  39. def _not(a):
  40.    return (~a) & 0xFFFFFFFF
  41.  
  42. def _dec(a):
  43.    return (a - 1) & 0xFFFFFFFF
  44.  
  45. def _inc(a):
  46.    return (a + 1) & 0xFFFFFFFF
  47.  
  48. '''
  49.  
  50. code_end = """    a2 = eax
  51.    a3 = edi
  52.    a4 = ebx
  53.    return a1, a2, a3, a4
  54.  
  55. if __name__ == '__main__':
  56.    # from struct import unpack
  57.    # u = lambda x: unpack('I', x)[0]
  58.  
  59.    # h = '43df6e922f0ad4127ef86627a9156601'.decode('hex')
  60.    # i = 0
  61.    # a = h[i:i+4]
  62.    # i = 4
  63.    # b = h[i:i+4]
  64.    # i = 8
  65.    # c = h[i:i+4]
  66.    # i = 12
  67.    # d = h[i:i+4]
  68.    # print '%08X %08X %08X %08X' % (u(a), u(b), u(c), u(d))
  69.    # a, b, c, d = encrypt(u(a), u(b), u(c), u(d))
  70.    in_ = [0x926EDF43, 0x12D40A2F, 0x2766F87E, 0x016615A9]
  71.    out = [0xAF8FF516, 0x39DA6102, 0x8AD9A164, 0x8B218C70]
  72.    print '%08X %08X %08X %08X' % (in_[0], in_[1], in_[2], in_[3])
  73.    a, b, c, d = encrypt(in_[0], in_[1], in_[2], in_[3])
  74.    print '%08X %08X %08X %08X' % (a, b, c, d)
  75.    print '%08X %08X %08X %08X' % (out[0], out[1], out[2], out[3])
  76. """
  77.  
  78. class DecodeRotate:
  79.     def __init__(self, begin, end, pos, used):
  80.         self.begin = begin
  81.         self.end = end
  82.         self.pos = pos
  83.         self.used = used
  84.        
  85.         self.op1 = GetOpnd(pos, 0)
  86.         self.op2 = GetOpnd(pos, 1)
  87.  
  88.         self.addesses = []
  89.         self.addesses.append(pos)
  90.  
  91.         self.count_init_addr = 0
  92.         self.value_init_addr = 0
  93.         self.neg_addr = 0
  94.  
  95.     def process_shifts(self):
  96.         ops = [self.op1, self.op2]
  97.         ops_o = ops
  98.         pos = self.pos
  99.         shifts_addr = []
  100.         while len(ops) > 0:
  101.             while pos > self.begin:
  102.                 pos = PrevHead(pos)
  103.                 if GetMnem(pos).startswith('sh') and GetOpnd(pos, 0) in ops and pos not in self.addesses and pos not in self.used:
  104.                     self.addesses.append(pos)
  105.                     ops.remove(GetOpnd(pos, 0))
  106.                     shifts_addr.append(pos)
  107.                     break
  108.                 elif GetMnem(pos) == 'mov' and GetOpnd(pos, 0) in ops and pos not in self.addesses and pos not in self.used:
  109.                     self.addesses.append(pos)
  110.                     ops.remove(GetOpnd(pos, 0))
  111.                     ops.append(GetOpnd(pos, 1))
  112.                     ops_o = ops
  113.  
  114.         and_addr = []
  115.         while len(shifts_addr) > 0:
  116.             pos = max(shifts_addr)
  117.             and_op = 'ecx'
  118.             while pos > self.begin:
  119.                 pos = PrevHead(pos)
  120.                 if GetMnem(pos) == 'mov' and GetOpnd(pos, 0) == and_op and pos not in self.addesses:
  121.                     and_op = GetOpnd(pos, 1)
  122.                     self.addesses.append(pos)
  123.                 elif GetMnem(pos) == 'and' and GetOpnd(pos, 0) == and_op and GetOpnd(pos, 1) == '1Fh' and pos not in self.addesses:
  124.                     self.addesses.append(pos)
  125.                     shifts_addr.remove(max(shifts_addr))
  126.                     and_addr.append(pos)
  127.                     break
  128.  
  129.         addr = self.find_count_init(and_addr)
  130.         if addr is not None:
  131.             self.find_ops_init(ops_o)
  132.             self.find_neg(addr)
  133.  
  134.     def find_neg(self, addr):
  135.         op1 = GetOpnd(addr, 0)
  136.         op2 = GetOpnd(addr, 1)
  137.         while addr < self.pos:
  138.             addr += ItemSize(addr)
  139.             mnem = GetMnem(addr)
  140.             if mnem == 'neg' and GetOpnd(addr, 0) in [op1, op2]:
  141.                 self.addesses.append(addr)
  142.                 break
  143.             elif mnem == 'mov' and GetOpnd(addr, 1) in [op1, op2] and GetOpType(addr, 1) != 5 and addr in self.addesses:
  144.                 if GetOpnd(addr, 1) == op1:
  145.                     op1 = GetOpnd(addr, 0)
  146.                 elif GetOpnd(addr, 1) == op2:
  147.                     op2 = GetOpnd(addr, 0)
  148.         else:
  149.             print 'find_neg error', hex(self.pos)
  150.             print op1, op2
  151.             pass
  152.  
  153.     def find_ops_init(self, ops):
  154.         count = 0
  155.         op1 = GetOpnd(self.pos, 0)
  156.         op2 = GetOpnd(self.pos, 1)
  157.         pos1 = self.pos
  158.         while pos1 > self.begin:
  159.             count += 1
  160.             if count > 60:
  161.                 self.addesses = []
  162.                 print '-', hex(self.pos)
  163.                 break
  164.             pos1 = PrevHead(pos1)
  165.             if GetMnem(pos1) == 'mov' and GetOpType(pos1, 1) != 5 and GetOpnd(pos1, 0) in [op1, op2]:
  166.                 self.addesses.append(pos1)
  167.                 if GetOpnd(pos1, 1) in [op1, op2]:
  168.                     self.value_init_addr = pos1
  169.                     break
  170.                 elif GetOpnd(pos1, 0) == op1:
  171.                     op1 = GetOpnd(pos1, 1)
  172.                 elif GetOpnd(pos1, 0) == op2:
  173.                     op2 = GetOpnd(pos1, 1)
  174.                 else:
  175.                     print('Hmmm')
  176.    
  177.     def find_count_init(self, starts):
  178.         pos = max(starts)
  179.         op1 = GetOpnd(pos, 0)
  180.         pos1 = min(starts)
  181.         op2 = GetOpnd(pos1, 0)
  182.         count = 0
  183.         while pos > min(starts):
  184.             if count > 60:
  185.                 self.addesses = []
  186.                 print 'find_count_init (stage #1, count end)', hex(self.pos)
  187.                 return None
  188.             pos = PrevHead(pos)
  189.             if GetMnem(pos) in ['mov', 'lea'] and GetOpType(pos, 1) != 5 and GetOpnd(pos, 0) == op1 and pos not in self.addesses:
  190.                 op1 = GetOpnd(pos, 1)
  191.                 self.addesses.append(pos)
  192.                 # if GetOpnd(pos, 0) == op1:
  193.                 #     op1 = GetOpnd(pos, 1)
  194.                 # elif GetOpnd(pos, 0) == op2:
  195.                 #     op2 = GetOpnd(pos, 1)
  196.             # elif GetMnem(pos) == 'neg' and GetOpnd(pos, 0) == op1 and self.neg_addr == 0:
  197.             #     self.neg_addr = pos
  198.             #     self.addesses.append(addesses)
  199.             count += 1
  200.         # else:
  201.         #     self.addesses = []
  202.         #     print 'find_count_init (stage #1, count end)', hex(self.pos)
  203.         #     return None
  204.  
  205.         count = 0
  206.        
  207.         while pos1 > self.begin:
  208.             if count > 60:
  209.                 self.addesses = []
  210.                 print 'find_count_init (stage #2, count end)', hex(self.pos)
  211.                 return None
  212.             pos1 = PrevHead(pos1)
  213.             if GetMnem(pos1) in ['mov', 'lea'] and GetOpType(pos1, 1) != 5 and GetOpnd(pos1, 0) in [op1, op2] and pos1 not in self.addesses:
  214.                 self.addesses.append(pos1)
  215.                 if GetOpnd(pos1, 1) in [op1, op2]:
  216.                     self.count_init_addr = pos1
  217.                     return pos1
  218.                 elif GetOpnd(pos1, 0) == op1:
  219.                     op1 = GetOpnd(pos1, 1)
  220.                 elif GetOpnd(pos1, 0) == op2:
  221.                     op2 = GetOpnd(pos1, 1)
  222.                 else:
  223.                     print('Hmmm')
  224.             # elif GetMnem(pos) == 'neg' and GetOpnd(pos, 0) in [op1, op2] and self.neg_addr == 0:
  225.             #     self.neg_addr = pos
  226.             #     self.addesses.append(addesses)
  227.             count += 1
  228.  
  229.     def do(self):
  230.         self.process_shifts()
  231.  
  232.     def get_addresses(self):
  233.         self.addesses.sort()
  234.         return self.addesses
  235.  
  236.     def get_instruction(self):
  237.         op = None
  238.         self.addesses.sort()
  239.         for addr in self.addesses:
  240.             if GetMnem(addr) == 'neg':
  241.                 op = GetOpnd(addr, 0)
  242.             if op is not None and GetMnem(addr) == 'mov' and GetOpnd(addr, 1) == op:
  243.                 op = GetOpnd(addr, 0)
  244.             if op is not None and GetMnem(addr).startswith('sh') and op == 'ecx':
  245.                 op0 = GetOpnd(self.pos, 0)
  246.                 op1 = GetOpnd(self.value_init_addr, 1)
  247.                 op2 = GetOpnd(self.count_init_addr, 1)
  248.                 mnem = '_rol' if GetMnem(addr) == 'shr' else '_ror'
  249.                 return '%s = %s(%s, %s)' % (op0, mnem, op1, op2)
  250.  
  251.  
  252. class Decoder:
  253.     def __init__(self, begin, end):
  254.         self.begin = begin
  255.         self.end = end
  256.  
  257.         self.addesses = []
  258.         self.blocks = []
  259.  
  260.     def do(self):
  261.         pos = self.begin
  262.         count = 0
  263.         while pos < self.end:
  264.             pos += ItemSize(pos)
  265.             if GetMnem(pos) == 'or' and GetOpType(pos, 1) != 5:
  266.                 rot = DecodeRotate(self.begin, self.end, pos, self.addesses)
  267.                 rot.do()
  268.                 addrs = rot.get_addresses()
  269.                 self.addesses.extend(addrs)
  270.                 self.blocks.append(addrs)
  271.                 print rot.get_instruction()
  272.                 # if count > 1:
  273.                 #     break
  274.                 count += 1
  275.  
  276.     def colorize(self):
  277.         pos = self.begin
  278.         while pos < self.end:
  279.             SetColor(pos, CIC_ITEM, 0xFFFFFF)
  280.             pos += ItemSize(pos)
  281.  
  282.         for block in self.blocks:
  283.             color = randint(0x888888, 0xDDDDDD)
  284.             for addr in block:
  285.                 SetColor(addr, CIC_ITEM, color)
  286.  
  287.         return len(set(self.addesses))
  288.  
  289.  
  290. class CodeGenerator:
  291.     def __init__(self, begin, end, blocks):
  292.         self.begin = begin
  293.         self.end = end
  294.         self.blocks = blocks
  295.  
  296.     def decode(self, pos):
  297.         mnem = GetMnem(pos)
  298.         op0 = GetOpnd(pos, 0)
  299.         op1 = op0
  300.         op2 = GetOpnd(pos, 1)
  301.         if mnem in ['push', 'pop']:
  302.             return ''
  303.         if GetOpType(pos, 1) == 5:
  304.             m = re.search('\-?([0-9A-F]+)h?', op2)
  305.             op2 = '0x%s' % m.group(1)
  306.         if mnem == 'lea':
  307.             if GetOpType(pos, 1) == 4:
  308.                 m = re.search('\[(e\w\w)(\+|-)([0-9A-F]+)h?\]', op2)
  309.                 op1 = m.group(1)
  310.                 mnem = m.group(2)
  311.                 op2 = '0x%s' % m.group(3)
  312.             elif GetOpType(pos, 1) == 3:
  313.                 m = re.search('\[(e\w\w)(\+|-)(.+)\]', op2)
  314.                 op1 = m.group(1)
  315.                 mnem = m.group(2)
  316.                 op2 = m.group(3)
  317.         elif mnem == 'imul':
  318.             op1 = op2
  319.             op2 = GetOpnd(pos, 2)
  320.         else:
  321.             if GetOpType(pos, 1) == 4:
  322.                 m = re.search('\[ebp\+(.+)\]', op2)
  323.                 op2 = m.group(1)
  324.             if GetOpType(pos, 0) == 4:
  325.                 m = re.search('\[ebp\+(.+)\]', op0)
  326.                 op0 = m.group(1)
  327.                 op1 = op0
  328.             if GetOpType(pos, 1) == 3:
  329.                 m = re.search('\[(.+)\]', op2)
  330.                 op2 = m.group(1)
  331.             if GetOpType(pos, 0) == 3:
  332.                 m = re.search('\[(.+)\]', op0)
  333.                 op0 = m.group(1)
  334.                 op1 = op0
  335.             if GetOpnd(pos, 1) == 'cl':
  336.                 op2 = 'ecx'
  337.  
  338.  
  339.         if mnem == 'mov':
  340.             return '%s = %s' % (op0, op2)
  341.         elif GetOpType(pos, 1) == 0:
  342.             return '%s = _%s(%s)' % (op0, mnem, op1)
  343.         elif mnem in ['-', '+']:
  344.             return '%s = _%s(%s, %s)' % (op0, 'sub' if mnem == '-' else 'add', op1, op2)
  345.         elif mnem in ['add', 'sub', 'and', 'xor', 'or', 'shr', 'shl', 'ror', 'rol', 'imul']:
  346.             return '%s = _%s(%s, %s)' % (op0, mnem, op1, op2)
  347.         else:
  348.             Exception('Error [mnem = %s, op0 = %s, op1 = %s, op2 = %s]' % (mnem, op0, op1, op2))
  349.    
  350.     def generate(self):
  351.         with open('/home/roman/encrypt.py', 'w') as f:
  352.             pos = self.begin
  353.             skip_addr = [0x0040DDA2, 0x0040DDAD, 0x0041B514, 0x0041B548]
  354.             f.write(code)
  355.             f.write('def encrypt(ecx, edx, a3, a4):\n')
  356.             while pos < self.end:
  357.                 if pos not in skip_addr:
  358.                     f.write('    ' + self.decode(pos) + '\n')
  359.                 pos += ItemSize(pos)
  360.             f.write(code_end)
  361.  
  362. def main():
  363.     begin = 0x0040DD80
  364.     end = 0x0041B562
  365.  
  366.     decoder = Decoder(begin, end)
  367.     decoder.do()
  368.     print 22127 - decoder.colorize()
  369.     # gen = CodeGenerator(0x0040DD86, 0x0041B54F, [])
  370.     # gen.generate()
  371.  
  372. if __name__ == '__main__':
  373.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement