AVX2指令集逆向,主要解题思路是使用idapython脚本逆向求解
先把ymm0 - ymm1寄存器赋值
再用 IDAPython 统计加密用到的指令:
ea=0x140001081 # 起始地址
opcode=set() # 利用集合自动去重
while True:
if ea>=0x0140007F17:
break
opcode.add(print_insn_mnem(ea))
ea=next_head(ea) # 到达下个指令的地址
print(opcode)
得到
{'vpermd', 'vpshufb', 'vpxor', 'vpsubb', 'vpaddb'}
?这里的ymm1就是最后的加密flag
根据指令具体意思用idapython逆向求解。
intel官方指令手册
import numpy
def vpaddb(a,b):
global num
for i in range(32):
num[a][i]+=num[b][i]
def vpsubb(a,b):
global num
for i in range(32):
num[a][i]-=num[b][i]
def vpxor(a,b):
global num
for i in range(32):
num[a][i]^=num[b][i]
def vpshufb(a,b):
global num
c=[0]*32
for i in range(16):
if num[b][i]&0x80:
c[i]=0
else:
c[i]=num[a][num[b][i]&0xF]
if num[b][i+16]&0x80:
c[i+16]=0
else:
c[i+16]=num[a][16+(num[b][i+16]&0xF)]
num[a]=c
def invvpshufb(a,b):
global num
c=[0]*32
for i in range(16):
if num[b][i]&0x80:
c[i]=0
else:
c[num[b][i]&0xF]=num[a][i]
if num[b][i+16]&0x80:
c[i+16]=0
else:
c[16+(num[b][i+16]&0xF)]=num[a][i+16]
num[a]=c
def vpermd(a,b):
global num
c=[0]*32
for i in range(8):
c[i*4]=num[a][num[b][i*4]*4]
c[i*4+1]=num[a][num[b][i*4]*4+1]
c[i*4+2]=num[a][num[b][i*4]*4+2]
c[i*4+3]=num[a][num[b][i*4]*4+3]
num[a]=c
def invvpermd(a,b):
global num
c=[0]*32
for i in range(8):
c[num[b][i*4]*4]=num[a][i*4]
c[num[b][i*4]*4+1]=num[a][i*4+1]
c[num[b][i*4]*4+2]=num[a][i*4+2]
c[num[b][i*4]*4+3]=num[a][i*4+3]
num[a]=c
op=[]
flag=[147,203,231,147,169,129,13,182,216,221,156,127,192,77,205,240,0,160,159,34,137,239
,84,93,239,0,141,254,94,76,208,236]
num=numpy.uint8([[104,103,97,109,101,123,114,105,103,104,116,95,121,111,117,114,95,
97,115,109,95,105,115,95,103,111,111,100,33,33,125,0],
[
240,255,100,38,242,143,64,238,238,39,7,239,136,10,33,20,195,252,112,229,168,243,245
,26,212,60,177,12,229,188,185,27],
[
13,192,132,197,14,128,80,255,40,26,128,72,29,193,227,29,52,81,155,53,188,213,244,195,196,64,144,7,42,192,45,144],
[
137,161,62,192,229,20,95,197,95,20,176,208,37,31,232,245,176,52,54,194,199,160,178,
60,94,126,156,164,152,232,84,11],
[
51,95,98,104,13,100,168,255,143,153,167,148,158,154,41,52,39,54,214,130,194,109,232
,170,150,74,101,192,12,55,25,201],
[
143,33,168,55,67,9,7,51,166,135,76,74,161,116,75,230,85,19,91,63,28,215,185,158,57,
96,29,198,145,138,54,139],
[ 0,1,8,9,10,2,3,4,5,12,13,14,6,7,11,15, 0,6,7,8,9,10,2,3,4,5,13,14,11,12,1,15],
[ 0,0,0,0,4,0,0,0,5,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,6,0,0,0,7,0,0,0]])#八个寄存器
ea=0x140001081
while True : #运行一遍汇编,验证加密过程是否正确,并得到ymm1~ymm7的数据
if ea >= 0x0140007F17:
break
opcode=print_insn_mnem(ea) # 得到汇编助记符
opnum1=int(print_operand(ea,0)[-1]) #得到第一个操作数的序号(即ymm0取0)
opnum2=int(print_operand(ea,1)[-1])
opnum3=int(print_operand(ea,2)[-1])
op.append([opcode,opnum1,opnum2,opnum3])
if opcode=='vpaddb':
vpaddb(opnum1,opnum3)
elif opcode=='vpsubb':
vpsubb(opnum1,opnum3)
elif opcode=='vpxor':
vpxor(opnum1,opnum3)
elif opcode=='vpshufb':
vpshufb(opnum1,opnum3)
elif opcode=='vpermd':
vpermd(opnum1,opnum2)
ea=next_head(ea)
num[0]=flag
for i in op[::-1]: # 倒序解密
if i[0]=='vpaddb':
vpsubb(i[1],i[3])
elif i[0]=='vpsubb':
vpaddb(i[1],i[3])
elif i[0]=='vpxor':
vpxor(i[1],i[3])
elif i[0]=='vpshufb':
invvpshufb(i[1],i[3])
elif i[0]=='vpermd':
invvpermd(i[1],i[2])
for i in num[0]:
try:
print(chr(i),end='')
except UnicodeEncodeError:
print(i,end='')
用idapython运行得到flag
hgame{right_your_asm_is_good!!}
其他师傅的爆破做法
|