Guest User

canyoucrackit VM in Python

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