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() |