vm初探

# PREFACE:最后两个逆向题,其实更像 pwn 的入门 vm,写个 orw,最后一题需要用各种方法 bruteforce & leak opcode(由于附件不同这里 exp 相当于一个思路)
# 直白的 orw

21.1

(ps. 后面看这里有点问题的,偏移其实不对,但是可以通,很奇妙,可能是有什么奇妙巧合?)

from pwn import *
context(os = 'linux',arch = 'amd64')
# context(log_level='debug')
# context(terminal=['tmux','splitw','-h'])
# p = gdb.debug('./babyrev_level21.0','b *interpret_sys + 156\nb *interpret_sys + 491\nb *interpret_sys + 659')
p = process(['strace','./babyrev_level21.1'])
# p = process('./babyrev_level21.1')
def register(name):
    match name:
        case 'opcode[1024]':
            return 64
        case 'opcode[1025]':
            return 1
        case 'opcode[1026]':
            return 16
        case 'opcode[1027]':
            return 4
        case 'opcode[1028]':
            return 8
        case 'opcode[1029]':
            return 32
    print('err register')
def interpret_instruction(name):
    match name:
        case 'interpret_imm':
            return 0x200
        case 'interpret_add':
            return 0x400
        case 'interpret_stk':
            return 0x800
        case 'interpret_stm':
            return 0x100
        case 'interpret_ldm':
            return 0x1000
        case 'interpret_cmp':
            return 0x8000
        case 'interpret_jmp':
            return 0x2000
        case 'interpret_sys':
            return 0x4000
    print('err instruction')
def interpret_imm(regs,value):
    return interpret_instruction('interpret_imm') + register(regs) + (value << 16)
def interpret_stm():
    # opcode[1025] = offset
    # opcode[1026] = value
    return interpret_instruction('interpret_stm') + (register('opcode[1025]')) + (register('opcode[1026]') << 16)
def interpret_sys(name):
    match name:
        case 'open':
            return 0x20
        case 'read_code':
            return 0x4
        case 'read':
            return 0x8
        case 'write':
            return 0x2
        case 'sleep':
            return 0x10
        case 'exit':
            return 0x1
    print('err sys')
def open():
    # opcode[opcode[1024] + 768] = addr
    # opcode[1024] = fd
    # opcode[1026] = len
    return interpret_sys('open') + interpret_instruction('interpret_sys') + (register('opcode[1024]') << 16)
def read():
    # opcode[1024] = fd
    # opcode[1025] = ret len
    return interpret_sys('read') + interpret_instruction('interpret_sys') + (register('opcode[1025]') << 16)
def write():
    # opcode[1024] = fd
    return interpret_sys('write') + interpret_instruction('interpret_sys') + (register('opcode[1025]') << 16)
def exitPro():
    return interpret_sys('exit') + interpret_instruction('interpret_sys')
opcode_func = '''
interpret_imm('opcode[1025]',768) # offset
interpret_imm('opcode[1026]',ord('/')) # value
interpret_stm()
interpret_imm('opcode[1025]',769) # offset
interpret_imm('opcode[1026]',ord('f')) # value
interpret_stm()
interpret_imm('opcode[1025]',770) # offset
interpret_imm('opcode[1026]',ord('l')) # value
interpret_stm()
interpret_imm('opcode[1025]',771) # offset
interpret_imm('opcode[1026]',ord('a')) # value
interpret_stm()
interpret_imm('opcode[1025]',772) # offset
interpret_imm('opcode[1026]',ord('g')) # value
interpret_stm()
interpret_imm('opcode[1024]',0) # addr = opcode[0 + 768]
interpret_imm('opcode[1025]',0)
interpret_imm('opcode[1026]',0)
open()
interpret_imm('opcode[1026]',0x50) # len
read()
interpret_imm('opcode[1024]',1)
interpret_imm('opcode[1025]',0)
interpret_imm('opcode[1026]',0x50) # len
write()
exitPro()
'''
opcode = []
opcode_func = opcode_func.split('\n')
# print(opcode_func)
for i in opcode_func:
    if (i == ''):
        continue
    p48 = eval(i)
    opcode.append(p48 & 0xff)
    opcode.append((p48 & 0xff00) >> 8)
    opcode.append((p48 & 0xff0000) >> 16)
opcode+=([0] * (0x300 - len(opcode)))
a = opcode
a = b''.join([bytes([i]) for i in a])
# print(a)
p.send(a)
p.interactive()
# 随机化 opcode 的 orw

22.0

爆破的思路:

种子一共 0xff 个,没有尝试直接爆,徒手一步一步做的(注释掉的就是思路),从 exit 为入口点一步一步推一步一步还原(这里最后的 open 只有三个可能的值 1|8|64 ,直接手试了):

from pwn import *
context(os = 'linux',arch = 'amd64')
# context(log_level='debug')
# context(terminal=['tmux','splitw','-h'])
# p = gdb.debug('./babyrev_level21.0','b *interpret_sys + 156\nb *interpret_sys + 491\nb *interpret_sys + 659')
# p = process(['strace','./babyrev_level22.0'])
# ------------------------------------------------
### sys:16  | exit:1
### interpret_imm:4 | opcode[1024]:8
### sleep:128
### read_code|read_memory:2/32                 opcode[1029]:64   none:4
### add:2
# ------------------------------------------------
## test exit
### sys:16, exit:1
# table = [1,2,4,8,16,32,64,0x80]
# for i in table:
#     for j in table:
#         a = []
#         a.append(5)
#         a.append(j)
#         a.append(i)
#         a += [0] * 0x300
#         a = b''.join([bytes([i]) for i in a])
#         p = process('/challenge/babyrev_level22.0')
#         p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a)
#         h = p.recv(4096)
#         print(i)
#         print(j)
## test interpret_imm, opcode | search : "exit code 5"
# table = [1,2,4,8,16,32,64,0x80]
# for i in table:
#     for j in table:
#         a = []
#         a.append(5)
#         a.append(j)
#         a.append(i)
#         a.append(0)
#         a.append(16)
#         a.append(1)
#         a += [0] * 0x250
#         a = b''.join([bytes([i]) for i in a])
#         p = process('/challenge/babyrev_level22.0')
#         p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a)
#         h = p.recv(4096)
#         print(i)
#         print(j)
## test sleep 128
# table = [1,2,4,8,16,32,64,0x80]
# for i in table:
#     a = []
#     a.append(0x10)
#     a.append(8)
#     a.append(4) # opcode[1024] = 0
#     a.append(0x10)
#     a.append(i)
#     a.append(1) # sleep
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a)
#     p.interactive()
#     # print(h)
#     print(i)
# use exit and add can exploit all the regs
## find add first:2
# import time
# table = [1,2,4,8,16,32,64,0x80]
# for j in table:
#     print(j)
#     a = []
#     a.append(3)
#     a.append(8)
#     a.append(4) # opcode[1024] = 3
#     a.append(8)
#     a.append(8)
#     a.append(j) # test add
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a_byte = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a_byte)
#     time.sleep(0.1)
#     p.kill()
## test ldm
# 32
# table = [1,2,4,8,16,32,64,0x80]
# for j in table:
#     print(j)
#     a = []
#     a.append(3)
#     a.append(8)
#     a.append(4) # opcode[1024] = 10
#     a.append(8)
#     a.append(8)
#     a.append(j) # test ldm
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a_byte = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a_byte)
#     time.sleep(0.1)
#     p.kill()
## test stm
# 64
# table = [1,2,4,8,16,32,64,0x80]
# for j in table:
#     print(j)
#     a = []
#     a.append(3)
#     a.append(8)
#     a.append(4) # opcode[1024] = 3
#     a.append(8)
#     a.append(1)
#     a.append(j) # test stm opcode[768] = 3;
#     a.append(5)
#     a.append(8)
#     a.append(4) # opcode[1024] = 5 # failed to write
#     a.append(1)
#     a.append(8)
#     a.append(32) # ldm
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a_byte = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a_byte)
#     time.sleep(0.1)
#     p.kill()
# # # write
# # write:4
# table = [1,2,4,8,16,32,64,0x80]
# for j in table:
#     if (j == 16 or j == 128 or j == 2 or j == 32):
#         continue
#     print(j)
#     a = []
#     a.append(ord('^'))
#     a.append(8)
#     a.append(4) # opcode[1024] = ord('^')
#     a.append(8)
#     a.append(1)
#     a.append(64) # stm opcode[768] = ord('^');
#     a.append(1)
#     a.append(1)
#     a.append(4) # opcode[[1]] ++
#     a.append(8)
#     a.append(1)
#     a.append(64) # stm opcode[769] = ord('^');
#     a.append(2)
#     a.append(1)
#     a.append(4) # opcode[[1]] ++
#     a.append(8)
#     a.append(1)
#     a.append(64) # stm opcode[769] = ord('^');
#     for i in table: # all register = 1
#         if (i == 8 or i == 4 or i == 64):
#             continue
#         a.append(1)
#         a.append(i)
#         a.append(4)
#     a.append(1)
#     a.append(8)
#     a.append(4) # opcode[1024] = 1 # fd = io
#     a.append(1)
#     a.append(j)
#     a.append(1) # write
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a_byte = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a_byte)
#     time.sleep(0.3)
#     print(p.recv())
#     p.kill()
# ## opcode[1025]
# # 1
# table = [1,2,4,8,16,32,64,0x80]
# tmp_a = []
# tmp_a.append(ord('^'))
# tmp_a.append(8)
# tmp_a.append(4) # opcode[1024] = ord('^')
# tmp_a.append(8)
# tmp_a.append(1)
# tmp_a.append(64) # stm opcode[768] = ord('^');
# tmp_a.append(1)
# tmp_a.append(1)
# tmp_a.append(4) # opcode[[1]] ++
# tmp_a.append(8)
# tmp_a.append(1)
# tmp_a.append(64) # stm opcode[769] = ord('^');
# tmp_a.append(2)
# tmp_a.append(1)
# tmp_a.append(4) # opcode[[1]] ++
# tmp_a.append(8)
# tmp_a.append(1)
# tmp_a.append(64) # stm opcode[769] = ord('^');
# for k in table: # test_register = 1
#     a = tmp_a.copy()
#     # print(a)
#     if (k == 8 or k == 4 or k == 64):
#         continue
#     for i in table: # all register = 0
#         if (i == 8 or i == 4 or i == 64):
#             continue
#         a.append(0)
#         a.append(i)
#         a.append(4)
#     print(k)
#     a.append(2)
#     a.append(k)
#     a.append(4) # one register = 1    
#     a.append(1)
#     a.append(8)
#     a.append(4) # opcode[1024] = 1 # fd = io
#     a.append(1)
#     a.append(4)
#     a.append(1) # write
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a_byte = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a_byte)
#     time.sleep(0.1)
#     print(p.recv())
#     p.kill()
##  opcode[1025]
# 32
# table = [1,2,4,8,16,32,64,0x80]
# tmp_a = []
# tmp_a.append(ord('^'))
# tmp_a.append(8)
# tmp_a.append(4) # opcode[1024] = ord('^')
# tmp_a.append(8)
# tmp_a.append(1)
# tmp_a.append(64) # stm opcode[768] = ord('^');
# tmp_a.append(1)
# tmp_a.append(1)
# tmp_a.append(4) # opcode[[1]] ++
# tmp_a.append(ord('@'))
# tmp_a.append(8)
# tmp_a.append(4) # opcode[1024] = ord('^')
# tmp_a.append(8)
# tmp_a.append(1)
# tmp_a.append(64) # stm opcode[769] = ord('^');
# tmp_a.append(2)
# tmp_a.append(1)
# tmp_a.append(4) # opcode[[1]] ++
# tmp_a.append(ord('#'))
# tmp_a.append(8)
# tmp_a.append(4) # opcode[1024] = ord('^')
# tmp_a.append(8)
# tmp_a.append(1)
# tmp_a.append(64) # stm opcode[769] = ord('^');
# for k in table: # test opcode[1025]
#     if (k == 1 or k == 8 or k == 64 or k == 4):
#         continue
#     a = tmp_a.copy()
#     # print(a)
#     for i in table: # all register = 0
#         if (i == 8 or i == 4 or i == 64 or i == 1):
#             continue
#         a.append(0)
#         a.append(i)
#         a.append(4)
#     print(k)
#     a.append(1)
#     a.append(k)
#     a.append(4) # opcode[1025] # offset: 1  
#     a.append(1)
#     a.append(1)
#     a.append(4) # opcode[1026] # len: 1  
#     a.append(1)
#     a.append(8)
#     a.append(4) # opcode[1024] = 1 # fd = io
#     a.append(1)
#     a.append(4)
#     a.append(1) # write
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a_byte = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a_byte)
#     time.sleep(0.1)
#     print(p.recv())
#     p.kill()
# # read
# 32
# table = [1,2,4,8,16,32,64,0x80]
# for k in [2,32]: # test read
#     a = []
#     print(k)
#     a.append(1)
#     a.append(32)
#     a.append(4) # opcode[1025] # offset: 1  
#     a.append(1)
#     a.append(1)
#     a.append(4) # opcode[1026] # len: 1 
#     a.append(0)
#     a.append(8)
#     a.append(4) # opcode[1024] = 0 # fd = io
#     a.append(2)
#     a.append(k)
#     a.append(1) # read
#     a.append(1)
#     a.append(8)
#     a.append(4) # opcode[1024] = 1 # fd = io
#     a.append(1)
#     a.append(4)
#     a.append(1) # write
#     a.append(0)
#     a.append(16)
#     a.append(1) # exit
#     a_byte = b''.join([bytes([i]) for i in a])
#     p = process('/challenge/babyrev_level22.0')
#     p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a_byte)
#     time.sleep(0.1)
#     # print(p.recv())
#     p.interactive()
#     p.kill()
# ----------------------------------------------------------------------------------------------------------------------------------- #
#                                                               open -> 
# ----------------------------------------------------------------------------------------------------------------------------------- #
def register(name):
    if (name == 'opcode[1024]'):
        return 8
    if (name == 'opcode[1025]'):
        return 32
    if (name == 'opcode[1026]'):
        return 1
    if (name == 'opcode[1027]'):
        return 0
    if (name == 'opcode[1028]'):
        return 0
    if (name == 'opcode[1029]'):
        return 64
    print('err register')
def interpret_instruction(name):
    if (name == 'interpret_imm'):
        return 4 << 16
    if (name == 'interpret_add'):
        return 2 << 16
    if (name == 'interpret_stk'):
        return 0
    if (name == 'interpret_stm'):
        return 64 << 16
    if (name == 'interpret_ldm'):
        return 32 << 16
    if (name == 'interpret_cmp'):
        return 0
    if (name == 'interpret_jmp'):
        return 0
    if (name == 'interpret_sys'):
        return 1 << 16
    print('err instruction')
def interpret_imm(regs,value):
    return interpret_instruction('interpret_imm') + (register(regs) << 8) + (value)
def interpret_stm():
    # opcode[1025] = offset
    # opcode[1026] = value
    return interpret_instruction('interpret_stm') + (register('opcode[1025]') << 8) + (register('opcode[1026]'))
def interpret_sys(name):
    if (name == 'open'):
        return 8 << 8
    if (name == 'read_code'):
        return 2 << 8
    if (name == 'read'):
        return 32 << 8
    if (name == 'write'):
        return 4 << 8
    if (name == 'sleep'):
        return 128 << 8
    if (name == 'exit'):
        return 16 << 8
    print('err sys')
def open():
    # opcode[opcode[1024] + 768] = addr
    # opcode[1024] = fd
    # opcode[1026] = len
    return interpret_sys('open') + interpret_instruction('interpret_sys') + (register('opcode[1024]') )
def read():
    # opcode[1024] = fd
    # opcode[1025] = ret len
    return interpret_sys('read') + interpret_instruction('interpret_sys') + (register('opcode[1025]') )
def write():
    # opcode[1024] = fd
    return interpret_sys('write') + interpret_instruction('interpret_sys') + (register('opcode[1025]') )
def exitPro():
    return interpret_sys('exit') + interpret_instruction('interpret_sys')
opcode_func = '''
interpret_imm('opcode[1025]',0) # offset
interpret_imm('opcode[1026]',ord('/')) # value
interpret_stm()
interpret_imm('opcode[1025]',1) # offset
interpret_imm('opcode[1026]',ord('f')) # value
interpret_stm()
interpret_imm('opcode[1025]',2) # offset
interpret_imm('opcode[1026]',ord('l')) # value
interpret_stm()
interpret_imm('opcode[1025]',3) # offset
interpret_imm('opcode[1026]',ord('a')) # value
interpret_stm()
interpret_imm('opcode[1025]',4) # offset
interpret_imm('opcode[1026]',ord('g')) # value
interpret_stm()
interpret_imm('opcode[1024]',0) # addr = opcode[0 + 768]
interpret_imm('opcode[1025]',0)
interpret_imm('opcode[1026]',0)
open()
interpret_imm('opcode[1026]',0x50) # len
read()
interpret_imm('opcode[1024]',1)
interpret_imm('opcode[1025]',0)
interpret_imm('opcode[1026]',0x50) # len
write()
exitPro()
'''
opcode = []
opcode_func = opcode_func.split('\n')
# print(opcode_func)
for i in opcode_func:
    if (i == ''):
        continue
    p48 = eval(i)
    opcode.append(p48 & 0xff)
    opcode.append((p48 & 0xff00) >> 8)
    opcode.append((p48 & 0xff0000) >> 16)
opcode+=([0] * (0x300 - len(opcode)))
a = opcode
# print(a)
a = b''.join([bytes([i]) for i in a])
p = process('/challenge/babyrev_level22.0')
p.sendafter(b"This time, YOU'RE in control! Please input your yancode: ",a)
p.interactive()
p.kill()