#!/usr/bin/env python

"""
b = open('2de6945e34e83d51.linux.elf32','rb').read()
p = b.find('\x41\x8A\xC3\x04')
s0 = b[p:][:7334]
p = b.find('\x9C\x73\x10\xD5')
s1 = b[p:][:136]
p = b.find('\xF9\x5E\x5E\x28')
s2 = b[p:][:190]
p = b.find('\x54\xC7\xAB\xF9')
s3 = b[p:][:202]
open('stage0.bin','wb').write(s0)
open('stage1.bin','wb').write(s1)
open('stage2.bin','wb').write(s2)
open('stage3.bin','wb').write(s3)
"""

def opxor(s,p,a,b): # s[p] = w
  return s[:p] + chr(ord(a)^ord(b)) + s[p+1:]

def dis(stage, num=1337):
  reg = [0]*8
  mem = [0]*8
  wtf = 0
  
  i = 0
  test = 0
  code = stage[16:]
  key = stage[:16]
  
  print "code (%i) = %s..." % (len(code), code[:20].encode("hex").upper())
  print "key (%i) = %s..." % (len(key), key[:20].encode("hex").upper())
  
  stop = False
  while not stop:
    code = opxor(code, i, code[i], key[i%16])
    code = opxor(code, i+1, code[i+1], key[(i+1)%16])
    code = opxor(code, i+2, code[i+2], key[(i+2)%16])
    code = opxor(code, i+3, code[i+3], key[(i+3)%16])
    
    instr = ord(code[i])
    p = ord(code[i+1])
    v = (ord(code[i+2])<<8) | ord(code[i+3])
    c = code[i:][:4].encode("hex").upper()
  
    if instr == 0x10:
      print "%04x:  %s  mov reg[%i], %i" % (i,c,p,v)
    elif instr == 0x11:
      print "%04x:  %s  mov reg[%i], reg[%i]" % (i,c,p,v)
    elif instr == 0x12:
      print "%04x:  %s  xor reg[%i], %i" % (i,c,p,v)
    elif instr == 0x20:
      print "%04x:  %s  load reg[%i], mem[%i]" % (i,c,p,v)
    elif instr == 0x30:
      print "%04x:  %s  shl reg[%i], %i" % (i,c,p,v)
    elif instr == 0x31:
      print "%04x:  %s  shr reg[%i], %i" % (i,c,p,v)
    elif instr == 0x40:
      print "%04x:  %s  add reg[%i], %i" % (i,c,p,v)
    elif instr == 0x41:
      print "%04x:  %s  add reg[%i], reg[%i]" % (i,c,p,v)
    elif instr == 0x49:
      print "%04x:  %s  or reg[%i], %i" % (i,c,p,v)
    elif instr == 0x50:
      print "%04x:  %s  and reg[%i], %i" % (i,c,p,v)
    elif instr == 0x51:
      print "%04x:  %s  add reg[%i], reg[%i]" % (i,c,p,v)
    elif instr == 0x60:
      print "%04x:  %s  test reg[%i], %i" % (i,c,p,v)
    elif instr == 0x61:
      print "%04x:  %s  test reg[%i], reg[%i]" % (i,c,p,v)
    elif instr == 0xBB:
      print "%04x:  %s  jne %i" % (i,c,v-4)
    elif instr == 0xBC:
      print "%04x:  %s  jmp %i" % (i,c,v-4)
    elif instr == 0x70:
      print "%04x:  %s  num reg[%i] ; %i" % (i,c,p,num)
    elif instr == 0x71:
      print "%04x:  %s  wtf reg[%i] ; %i" % (i,c,p,wtf)
    elif instr == 0xA4:
      print "%04x:  %s  call(code[%i], %i)" % (i,c,v,v)
      print "                 printf(\"%%s\", code[%i])" % v
    elif instr == 0xA5:
      print "%04x:  %s  printf(\"%%d\", reg[%i])" % (i,c,p)
    elif instr == 0xA6:
      print "%04x:  %s  putchar('\\n')" % (i,c)
    elif instr == 0xA7:
      print "%04x:  %s  call(code[%i], %i)" % (i,c,v,v)
      print "                 puts(code[%i])" % v
    elif instr == 0xDE:
      print "%04x:  %s  exit 0 -> OK" % (i,c)
      stop = True
    elif instr == 0xC0:
      print "%04x:  %s  exit -1 -> FAILED" % (i,c)
      stop = True
    else:
      print "%04x:  %s  undefined /!\\" % (i,c)
    
    i += 4
  
  print "finished"

if __name__ == "__main__":
  s1 = open('stage0.bin','rb').read()
  s2 = open('stage1.bin','rb').read()
  s3 = open('stage2.bin','rb').read()
  s4 = open('stage3.bin','rb').read()
  
  print "-- Stage 0"
  dis(s1)
  print "-- Stage 1"
  dis(s2)
  print "-- Stage 2"
  dis(s3)
  print "-- Stage 3"
  dis(s4)
