مثال اولی که به آن میپردازیم مربوط به مسابقهی خاصی نیست ولی سوال بسیار خوبی است. فایل این چالش را میتوانید از
اینجا
دریافت کنید.
در ابتدا تلاش کنید که خودتان این سوال را حل کنید سپس ویدیوی آن را ببینید.
اسکریپت حل سوال با r2pip:
#!/usr/bin/env python3
import r2pipe
import time
def opcode1(operand1, operand2, flag):
flag[operand1] = operand2
return flag
def opcode2(operand1, flag):
global xor_key
xor_key = flag[operand1]
return flag
def opcode3(operand1, flag):
res = xor_key ^ flag[operand1]
flag[operand1] = res
return flag
r2 = r2pipe.open("./vm1.exe")
r2.cmd('aaa')
#print(r2.cmd("afl"))
r2.cmd("s 0x404040")
flag_data = (r2.cmd("p8 255"))
flag = [0] *256
for i in range(int(len(flag_data)/2)):
flag [i] = int(flag_data[2*i:2*i+2] , 16)
xor = 0
r2.cmd("s 0x404040 + 0xff")
data = (r2.cmd("pxWq")).split()
for inx,d in enumerate(data):
d = d[2:]
tmp = [d[i:i+2] for i in range (0, 8, 2)][::-1]
data[inx] = "".join(tmp)
#print(d , data[inx])
data = "".join(data)
opcode = ""
operand1 = ""
operand2 = ""
opcode = data[:2]
counter = 2
while(opcode == "01" or opcode == "02" or opcode == "03"):
operand1 = int(data[counter:counter + 2] , 16)
counter += 2
operand2 = int(data[counter:counter + 2] , 16)
counter += 2
#print (opcode , operand1 , operand2)
#next
#time.sleep(1)
if opcode == "01":
flag = opcode1(operand1, operand2, flag)
elif opcode == "02":
flag = opcode2(operand1, flag)
else:
flag = opcode3(operand1, flag)
opcode = data[counter:counter + 2]
counter += 2
flag_str = ""
for i in range(len(flag)):
flag_str += chr(flag[i])
if chr(flag[i]) == "}":
break
print(flag_str)
اسکریپت حل سوال با IDAPython:
from idaapi import *
xor_key = 0
def one(operand1, operand2, vm_offset):
PatchByte(vm_offset+operand1, operand2)
return "opcode: 1"
def two(operand1, operand2, vm_offset):
global xor_key
xor_key = Byte(vm_offset + operand1)
return "opcode: 2"
def three(operand1, operand2, vm_offset):
res = xor_key ^ Byte(vm_offset + operand1)
PatchByte(vm_offset+operand1, res)
return "opcode: 3"
def vm_interpreter(code, operand1, operand2, vm_offset):
opcode = {
1: one,
2: two,
3: three
}
callback = opcode.get(code, lambda operand1, operand2,
vm_offset: "invalid opcode")
return callback(operand1, operand2, vm_offset)
def parse_vm_bytecode(vm_offset, size):
jmp = 0xff # vm virutal address bytecode offset
vm_code = vm_offset + 0xff
counter = 0
while(counter <= size - 3 - 0xff):
opcode = Byte(vm_code+counter)
counter += 1
operand1 = Byte(vm_code+counter)
counter += 1
operand2 = Byte(vm_code+counter)
vm_interpreter(opcode, operand1, operand2, vm_offset)
counter += 1
def print_flag(vm_offset):
print GetString(vm_offset, -1, ASCSTR_C)
def decode_vm(vm_offset, size):
parse_vm_bytecode(vm_offset, size)
print_flag(vm_offset)
decode_vm(0x404040, 0x1fb)