2018护网杯线上 APM233
MFC42的逆向
一共四层验证,IDA打开后基本全红,直接按P创建函数
花指令格式为jz address+1; jnz address+1;
,因此显示出address处的opcode,按D设为数据,address+1处创建函数,平衡栈帧即可
主流程
Check1
第一层与字符串1d2e3c4a比较
Check2
z3直接计算
from z3 import * from pwn import *
Dr0 = BitVec('Dr0',32) Dr1 = BitVec('Dr1',32) Dr2 = BitVec('Dr2',32) Dr3 = BitVec('Dr3',32) s = Solver()
s.add(Dr0 <= 0x7FFFFFFF) s.add(Dr1 <= 0x7FFFFFFF) s.add(Dr2 <= 0x7FFFFFFF) s.add(Dr3 <= 0x7FFFFFFF) s.add(Dr1+Dr0 == 0x899a9d9c) s.add(Dr2+Dr1 == 0x384989ED) s.add(Dr3+Dr2 == 0x2B2C85BC) s.add(Dr0-Dr3 == 0xAFAFDC11)
s.check()
m = s.model()
Dr0 = int('%s'%m[Dr0]) Dr1 = int('%s'%m[Dr1]) Dr2 = int('%s'%m[Dr2]) Dr3 = int('%s'%m[Dr3]) ans = '%s%s%s%s'%(p32(Dr0).encode('hex'),p32(Dr1).encode('hex'),p32(Dr2).encode('hex'),p32(Dr3).encode('hex'))
print(ans)
|
不知道为什么我这里的数值和别人的不一样,算出来的也不一样。。。正确结果应该是efbe3323adde6666feca1313beba1414
Check3
各种反调试虚拟机检测,未检测到的返回值就是key: 0acb7935481efc12
Check4
要求玩家的位置不能与三个AI重合,玩家每次的可走的步数为1-4,AI的行动路线如下所示
a1 = [4, -1, 6, -1, 3, 2, 4, 1, 3, -1, 5, 1, 2, -1, 5, 1, 3, -2, 7, 0, 2, 3, 5, 0, 5, 0, 5, 2, 1, -2, 6, -1, 3, 3, 4, 0, 5, -1, 6, 0, 4, 0, 7, 0, 5, -2, 7, 2, 2, -1, 6, 2, 2, 1, 5, 0, 2, 0, 3, 0, 4, 0, 6, -1, 5, 0, 5, 3, 0, 5, 3, 2]
a2 = [2, 2, 3, 3, 3, -2, 7, 1, 1, 1, 5, 1, 0, 2, 5, 1, 0, 0, 4, 0, 7, 2, 2, 0, 4, 1, 3, 4, 0, 1, 6, -1, 5, -1, 3, 5, 1, 2, 5, 0, 5, 0, 2, 5, 1, 1, 5, 2, 2, 1, 2, 3, 5, -1, 4, 1, 2, -1, 7, 1, 2, 2, 1, 2, 5, 0, 5, 0, 5, -1, 3, 2]
a3 = [3, -1, 6, -1, 5, 0, 4, 0, 2, 5, 0, 5, 1, -1, 5, 1, 0, 2, 4, 0, 5, 0, 4, 0, 6, -1, 6, 1, 2, 1, 3, 3, 2, 3, 3, 0, 5, -1, 4, 0, 6, 0, 5, 0, 5, 1, 2, 2, 3, 0, 5, 5, 0, 0, 6, 2, -1, 1, 5, 1, 0, 3, 4, -1, 4, 5, 0, 2, 5, 1, 4, 1]
通过上述规则,可以得到玩家的路线为
[1, 4, 1, 3, 1, 4, 1, 2, 2, 3, 2, 1, 1, 4, 1, 1, 1, 4, 1, 4, 2, 3, 1, 4, 1, 4, 2, 1, 1, 4, 1, 3, 2, 3, 2, 3, 1, 4, 1, 4, 1, 4, 2, 3, 1, 4, 2, 2, 1, 4, 3, 2, 1, 4, 1, 1, 1, 4, 1, 2, 2, 3, 1, 4, 2, 3, 2, 3, 2, 3, 2, 3]
玩家的行动由输入b64encode后再将编码后的结果拆为两两一组
脚本
from base64 import b64decode,b64encode
def level4(): a1 = [4, -1, 6, -1, 3, 2, 4, 1, 3, -1, 5, 1, 2, -1, 5, 1, 3, -2, 7, 0, 2, 3, 5, 0, 5, 0, 5, 2, 1, -2, 6, -1, 3, 3, 4, 0, 5, -1, 6, 0, 4, 0, 7, 0, 5, -2, 7, 2, 2, -1, 6, 2, 2, 1, 5, 0, 2, 0, 3, 0, 4, 0, 6, -1, 5, 0, 5, 3, 0, 5, 3, 2] a2 = [2, 2, 3, 3, 3, -2, 7, 1, 1, 1, 5, 1, 0, 2, 5, 1, 0, 0, 4, 0, 7, 2, 2, 0, 4, 1, 3, 4, 0, 1, 6, -1, 5, -1, 3, 5, 1, 2, 5, 0, 5, 0, 2, 5, 1, 1, 5, 2, 2, 1, 2, 3, 5, -1, 4, 1, 2, -1, 7, 1, 2, 2, 1, 2, 5, 0, 5, 0, 5, -1, 3, 2] a3 = [3, -1, 6, -1, 5, 0, 4, 0, 2, 5, 0, 5, 1, -1, 5, 1, 0, 2, 4, 0, 5, 0, 4, 0, 6, -1, 6, 1, 2, 1, 3, 3, 2, 3, 3, 0, 5, -1, 4, 0, 6, 0, 5, 0, 5, 1, 2, 2, 3, 0, 5, 5, 0, 0, 6, 2, -1, 1, 5, 1, 0, 3, 4, -1, 4, 5, 0, 2, 5, 1, 4, 1]
pos1 = 0 pos2 = 0 pos3 = 0 pos4 = 0 choice = [] for i in range(len(a1)): pos1 += a1[i] pos2 += a2[i] pos3 += a3[i] if (pos4 + 4 != pos1) and (pos4 + 4 != pos2) and (pos4 + 4 != pos3): t = 4 elif (pos4 + 3 != pos1) and (pos4 + 3 != pos2) and (pos4 + 3 != pos3): t = 3 elif (pos4 + 2 != pos1) and (pos4 + 2 != pos2) and (pos4 + 2 != pos3): t = 2 else: t = 1 pos4 += t choice.append(t-1)
print choice
b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
print choice ans = '' for i in xrange(0,len(choice),3): t = (choice[i]<<4) + (choice[i+1]<<2) + choice[i+2] print t, ans+=b64[t]
print
print ans print b64decode(ans)
level2()
level4()
|
程序输入有时间限制,可以找到时间call直接jmp,也可以鼠标模拟
鼠标点击模拟脚本
from pymouse import * import time m = PyMouse()
k1 = "1d2e3c4a" key1 = list(k1) k2 = "efbe3323adde6666feca1313beba1414" key2 = list(k2) k3 = "0acb7935481efc12" key3 = list(k3) k4 = "21d03c42f365901cff" key4 = list(k4)
def mnclick(x, y): for i in range(y): if(x[i] == '0'): m.click(1075, 418) elif(x[i] == '1'): m.click(1118, 418) elif(x[i] == '2'): m.click(1162, 418) elif(x[i] == '3'): m.click(1205, 418) elif(x[i] == '4'): m.click(1075, 465) elif(x[i] == '5'): m.click(1118, 465) elif(x[i] == '6'): m.click(1162, 465) elif(x[i] == '7'): m.click(1205, 465) elif(x[i] == '8'): m.click(1075, 511) elif(x[i] == '9'): m.click(1118, 511) elif(x[i] == 'a'): m.click(1162, 511) elif(x[i] == 'b'): m.click(1205, 511) elif(x[i] == 'c'): m.click(1075, 558) elif(x[i] == 'd'): m.click(1118, 558) elif(x[i] == 'e'): m.click(1162, 558) elif(x[i] == 'f'): m.click(1205, 558) time.sleep(1) m.click(670, 624)
mnclick(key1, 8) mnclick(key2, 32) mnclick(key3, 16) mnclick(key4, 18)
|
按钮位置是用spy++查看窗口属性看到的
最后 flag{N0t_d1ff1cul7_r1ght?_3d34e}