Guest User

Untitled

a guest
Apr 20th, 2018
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.55 KB | None | 0 0
  1. # Python VM for canyoucrackit.co.uk stage 2.
  2. # This version single-steps and disassembles
  3. # Possible improvements
  4. #   - register dumps
  5. #   - tidy quickly hacked code
  6.  
  7. #
  8. # virtual machine architecture
  9. # ++++++++++++++++++++++++++++
  10. #
  11. # segmented memory model with 16-byte segment size (notation seg:offset)
  12. #
  13. # 4 general-purpose registers (r0-r3)
  14. # 2 segment registers (cs, ds equiv. to r4, r5)
  15. # 1 flags register (fl)
  16. #
  17. # instruction encoding
  18. # ++++++++++++++++++++
  19. #
  20. #           byte 1               byte 2 (optional)
  21. # bits      [ 7 6 5 4 3 2 1 0 ]  [ 7 6 5 4 3 2 1 0 ]
  22. # opcode      - - -            
  23. # mod               -          
  24. # operand1            - - - -
  25. # operand2                         - - - - - - - -
  26. #
  27. # operand1 is always a register index
  28. # operand2 is optional, depending upon the instruction set specified below
  29. # the value of mod alters the meaning of any operand2
  30. #   0: operand2 = reg ix
  31. #   1: operand2 = fixed immediate value or target segment (depending on instruction)
  32. #
  33. # instruction set
  34. # +++++++++++++++
  35. #
  36. # Notes:
  37. #   * r1, r2 => operand 1 is register 1, operand 2 is register 2
  38. #   * movr r1, r2 => move contents of register r2 into register r1
  39. #
  40. # opcode | instruction | operands (mod 0) | operands (mod 1)
  41. # -------+-------------+------------------+-----------------
  42. # 0x00   | jmp         | r1               | r2:r1
  43. # 0x01   | movr        | r1, r2           | rx,   imm
  44. # 0x02   | movm        | r1, [ds:r2]      | [ds:r1], r2
  45. # 0x03   | add         | r1, r2           | r1,   imm
  46. # 0x04   | xor         | r1, r2           | r1,   imm
  47. # 0x05   | cmp         | r1, r2           | r1,   imm
  48. # 0x06   | jmpe        | r1               | r2:r1
  49. # 0x07   | hlt         | N/A              | N/A
  50. #
  51. # flags
  52. # +++++
  53. #
  54. # cmp r1, r2 instruction results in:
  55. #   r1 == r2 => fl = 0
  56. #   r1 < r2  => fl = 0xff
  57. #   r1 > r2  => fl = 1
  58. #
  59. # jmpe r1
  60. #   => if (fl == 0) jmp r1
  61. #      else nop
  62.  
  63. CS = 4
  64. DS = 5
  65.  
  66. class Instruction:
  67.     def __init__(self):
  68.         self.numbytes = 1
  69.         self.numops = 1
  70.         self.octet = 0
  71.         self.opcode = 0
  72.         self.mod = 0
  73.         self.operand1 = 0
  74.         self.operand2 = 0
  75.  
  76. class Cpu:
  77.     def __init__(self):
  78.         self.labelstrs = \
  79.         (
  80.             '%02x:%04x\t%02x   \t',
  81.             '%02x:%04x\t%02x %02x\t'
  82.         )
  83.         self.formatstrs = \
  84.         (
  85.             ('jmp     r%d',           'jmp     0x%02x:r%d'),
  86.             ('movr    r%d, r%d',      'movr    r%d, #0x%02x'),
  87.             ('movm    r%d, [ds:r%d]', 'movm    [ds:r%d], r%d'),
  88.             ('add     r%d, r%d',      'add     r%d, #0x%02x'),
  89.             ('xor     r%d, r%d',      'xor     r%d, #0x%02x'),
  90.             ('cmp     r%d, r%d',      'cmp     r%d, #0x%02x'),
  91.             ('jmpe    r%d',           'jmpe    0x%02x:r%d'),
  92.             ('hlt',                   'hlt')
  93.         )
  94.         self.swapoperands = ((0, 1), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 1), (0,0))
  95.         self.numoperands = ((1, 2), (2, 2), (2, 2), (2, 2), (2, 2), (2, 2), (1, 2), (0,0))
  96.         self.running = False
  97.         self.ip = 0x00
  98.         self.r = [0x00, 0x00, 0x00, 0x00, 0x00, 0x10]
  99.         self.fl = 0x00
  100.         self.firmware = (0xd2ab1f05, 0xda13f110)
  101.  
  102.         self.mem = [0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50,
  103.                     0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  104.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  105.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  106.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  107.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  108.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  109.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  110.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  111.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  112.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  113.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  114.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  115.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  116.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  117.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  118.                    
  119.                     0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8,
  120.                     0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9,
  121.                     0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
  122.                     0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
  123.                     0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
  124.                     0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56,
  125.                     0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9,
  126.                     0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69,
  127.                     0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60,
  128.                     0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8,
  129.                     0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d,
  130.                     0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67,
  131.                     0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a,
  132.                     0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9,
  133.                     0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e,
  134.                     0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  135.                    
  136.                     0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55,
  137.                     0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3,
  138.                     0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f,
  139.                     0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d,
  140.                     0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1,
  141.                     0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94,
  142.                     0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62,
  143.                     0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b,
  144.                     0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1,
  145.                     0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61,
  146.                     0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14,
  147.                     0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2,
  148.                     0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1,
  149.                     0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  150.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  151.                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  152.                    
  153.     def Fetch(self, extip=None):
  154.         instr = Instruction()
  155.         if extip is None:
  156.             extip = (self.r[CS] << 4) + self.ip
  157.         instr.octet = self.mem[extip]
  158.         instr.opcode = (instr.octet >> 5) & 0x7
  159.         instr.mod = (instr.octet >> 4) & 0x1
  160.         instr.operand1 = instr.octet & 0xf
  161.         instr.numops = self.numoperands[instr.opcode][instr.mod]
  162.         instr.numbytes = 1
  163.         if (instr.numops == 2):
  164.             instr.numbytes = 2
  165.             instr.operand2 = self.mem[extip+1]
  166.         return instr
  167.    
  168.     def Exec(self, instr):
  169.         if self.running:
  170.             target_set = False
  171.             op1 = instr.operand1
  172.             op2 = instr.operand2
  173.             if instr.opcode == 0x00: # jmp
  174.                 self.ip = self.r[op1]
  175.                 if (instr.mod == 1):
  176.                     self.r[CS] = op2
  177.                 print 'Jump to %02x:%04x (%06x)' % (self.r[CS], self.ip, (self.r[CS] << 4) + self.ip)
  178.                 target_set = True
  179.             elif instr.opcode == 0x01: # movr
  180.                 if (instr.mod == 0):
  181.                     # Register - replace op2 with what's in the register
  182.                     op2 = self.r[op2]
  183.                 self.r[op1] = op2
  184.                 print '0x%02x (%d) -> r%d' % (op2, op2, op1)
  185.             elif instr.opcode == 0x02: # movm
  186.                 if (instr.mod == 0):
  187.                     # Mem to reg
  188.                     idx = (self.r[DS] << 4) + self.r[op2]
  189.                     self.r[op1] = self.mem[idx]
  190.                     print '[%02x:%02x] (0x%02x (%d)) -> r%d' % (self.r[DS], self.r[op2], self.mem[idx], self.mem[idx], op1)
  191.                 else:
  192.                     # Reg to Mem
  193.                     idx = (self.r[DS] << 4) + self.r[op1]
  194.                     self.mem[idx] = self.r[op2]
  195.                     print 'r%d (0x%02x (%d)) -> [%02x:%02x]' % (op2, self.mem[idx], self.mem[idx], self.r[DS], self.r[op1])
  196.             elif instr.opcode == 0x03: # add
  197.                 if (instr.mod == 0):
  198.                     # Register
  199.                     self.r[op1] = (self.r[op1] + self.r[op2]) & 0xff # No overflow bit
  200.                     print 'r%d + r%d (0x%02x (%d)) -> r%d (0x%02x (%d))' % (op1, op2, self.r[op2], self.r[op2], op1, self.r[op1], self.r[op1])
  201.                 else:
  202.                     # Immediate
  203.                     self.r[op1] = (self.r[op1] + op2) & 0xff # No overflow bit
  204.                     print 'r%d + 0x%02x (%d) -> r%d (0x%02x (%d))' % (op1, op2, op2, op1, self.r[op1], self.r[op1])
  205.             elif instr.opcode == 0x04: # xor
  206.                 if (instr.mod == 0):
  207.                     # Register
  208.                     self.r[op1] = self.r[op1] ^ self.r[op2]
  209.                     print 'r%d ^ r%d (0x%02x (%d)) -> r%d (0x%02x (%d))' % (op1, op2, self.r[op2], self.r[op2], op1, self.r[op1], self.r[op1])
  210.                 else:
  211.                     # Immediate
  212.                     self.r[op1] = self.r[op1] ^ op2
  213.                     print 'r%d ^ 0x%02x (%d) -> r%d (0x%02x (%d))' % (op1, op2, op2, op1, self.r[op1], self.r[op1])
  214.             elif instr.opcode == 0x05: # cmp
  215.                 if (instr.mod == 0):
  216.                     # Register - replace op2 with what's in the register
  217.                     op2 = self.r[op2]
  218.                 self.fl = 1
  219.                 if (self.r[op1] == op2):
  220.                     self.fl = 0
  221.                 elif (self.r[op1] < op2):
  222.                     self.fl = 0xff
  223.                 print '0x%02x (%d) -> fl' % (self.fl, self.fl)
  224.             elif instr.opcode == 0x06: # jmpe
  225.                 if (self.fl == 0):
  226.                     self.ip = self.r[op1]
  227.                     if (instr.mod == 1):
  228.                         self.r[CS] = op2
  229.                     print 'Jump to %02x:%04x (%06x)' % (self.r[CS], self.ip, (self.r[CS] << 4) + self.ip)
  230.                     target_set = True
  231.                 else:
  232.                     print 'Jump (nop)'
  233.             elif instr.opcode == 0x07: # hlt
  234.                 self.running = False
  235.                 print 'Halt'
  236.             if (not target_set):
  237.                 self.ip += instr.numbytes
  238.         else:
  239.             print 'CPU not running'
  240.  
  241.     def PrintInstr(self, instr, loc=None):
  242.         fmtstr = self.formatstrs[instr.opcode][instr.mod]
  243.         lblstr = self.labelstrs[instr.numbytes - 1]
  244.         #ip = self.ip - instr.numbytes
  245.         if loc is None:
  246.             cs = self.r[CS]
  247.             ip = self.ip
  248.         else:
  249.             cs = loc >> 4
  250.             ip = loc & 0xF
  251.         ioc = instr.octet
  252.         op1 = instr.operand1
  253.         op2 = instr.operand2
  254.         if (instr.numops == 0):
  255.             print (lblstr % (cs, ip, ioc)) + fmtstr
  256.         elif (instr.numops == 1):
  257.             print (lblstr % (cs, ip, ioc)) + (fmtstr % op1)
  258.         elif (instr.numops == 2):
  259.             if self.swapoperands[instr.opcode][instr.mod]:
  260.                 print (lblstr % (cs, ip, ioc, op2)) + (fmtstr % (op2, op1))
  261.             else:
  262.                 print (lblstr % (cs, ip, ioc, op2)) + (fmtstr % (op1, op2))
  263.  
  264. # Instantiate CPU                
  265. cpu = Cpu()
  266.  
  267. # Execute the code in memory. Note it is self-modifying so the first block
  268. # of code at CS=0x00:00 modifies data to produce code at CS=0x10:0000
  269.  
  270. cpu.running = True
  271. while cpu.running:
  272.     instr = cpu.Fetch()
  273.     cpu.PrintInstr(instr)
  274.     cpu.Exec(instr)
  275.     # Uncomment the next line for single stepping
  276.     #raw_input("next...")
  277.  
  278. print 'Exited'
  279. outfile = open('memdump.bin', 'w')
  280. for i in cpu.mem:
  281.     outfile.write('%c' % i)
  282. outfile.close()
  283.  
  284. # Disassemble memory block. Note if you don't reinstantiate cpu, it will disassembled the self-modified code
  285. # Maybe stages of self-modification on the unknown other data blocks
  286.  
  287. i = len(cpu.mem)
  288. loc = 0
  289. while i:
  290.     instr = cpu.Fetch(loc)
  291.     cpu.PrintInstr(instr, loc)
  292.     loc += instr.numbytes
  293.     i -= instr.numbytes
Add Comment
Please, Sign In to add comment