2020-强网杯-wp

赛题出的很有水平啊,第一天出去玩了一天,第二天才开始做,只做出了这么几题,看了一下firmware是个虚拟机,再多点时间应该也可以出

侧防

这题比较简单,放在了,没有放在re分类,直接上脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
byte_4010 = [0x51, 0x57, 0x42, 0x6C, 0x6F, 0x67, 0x73]
target = "Lx|dTUwe\\IvNhCBOLqDNfW}ImFZCtiyxO\\PW^ebD"
f = []
for i in range(0, len(target), 4):
f.append(target[i + 1])
f.append(target[i + 2])
f.append(target[i + 3])
f.append(target[i])
flag = ""
for i, c in enumerate(f):
flag += chr((ord(c) - 65) ^ byte_4010[i % 7])
print(flag)
# flag{QWB_water_problem_give_you_the_score}

xx_warmup_obf

混淆+花指令+反调,从read或者strlen函数开始找起会比较方便,找到之后发现一位一位计算,为了节省时间,代码跑出一部分之后后面的flag可以直接猜出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from z3 import *

def RecurOr(flags, models, pos=0):
if pos <= len(flags) - 1:
return Or(models[flags[pos]] != flags[pos], RecurOr(flags, models, pos + 1))
else:
return Or(models[flags[pos]] != flags[pos])

f = [BitVec('v%d' % i, 16) for i in range(22)]
flag = []
solver = Solver()
for c in f:
solver.add(c >= 0x0)
solver.add(c <= 0xff)
solver.add(f[0] == ord('f'))
solver.add(f[1] == ord('l'))
solver.add(f[2] == ord('a'))
solver.add(f[3] == ord('g'))
solver.add(f[4] == ord('{'))
solver.add((f[5] * 0x1eb9d + f[2] * 0x40a8c + f[3] * 0x3fb3f + f[4] * 0xfffb82cd + f[1] * 0xffffea88 + f[0] * 0xfffda7c3) & 0xffffffff == 0xc78321)
solver.add((f[6] * 0xfffd185d + f[5] * 0xfffe032d + f[2] * 0xfffc468a + f[3] * 0xFFFC0EA3 + f[4] * 0xFFFE5277 + f[1] * 0xfffc4328 + f[0] * 0x44DE) & 0xffffffff == 0xF961DAEB)
solver.add((f[6] * 0x35770 + f[5] * 0x1CC39 + f[2] * 0x4851 + f[3] * 0xFFFFE5B9 + f[4] * 0x36D92 + f[1] * 0xFFFCF9E1 + f[0] * 0x37C38 + f[7] * 0x4186D)& 0xffffffff == 0x4B202E4)
solver.add((f[6] * 0xFFFC4AB1 + f[5] * 0x0CB64 + f[2] * 0x1309E + f[3] * 0xFFFB995E + f[4] * 0x2E940 + f[1] * 0xFFFEB612 + f[0] * 0xFFFC631A + f[7] * 0xFFFCAA83 + f[8] * 0x16A0C) & 0xffffffff == 0xFCDE9AB5)
solver.add((f[6] * 0x37EB9 + f[5] * 0xFFFDD238 + f[2] * 0xFFFBE2C0 + f[3] * 0x17977 + f[4] * 0x29D39 + f[1] * 0xFFFBB74E + f[0] * 0xFFFD6E33 + f[7] * 0xFFFF0427 + f[8] * 0xFFFD0153 + f[9] * 0xFFFF66A5) & 0xffffffff == 0xFBC7B90A)
solver.add((f[6] * 0x1DAAC + f[5] * 0xFFFE92AC + f[2] * 0xFFFF9AD4 + f[3] * 0x2C78D + f[4] * 0xFFFC69EE + f[1] * 0xFFFC1736 + f[0] * 0x47762 + f[7] * 0x28557 + f[8] * 0x27B6D + f[9] * 0xFFFF7F4E + f[10] * 0x2F9DF) & 0xffffffff == 0x1AF43AB)
solver.add((f[6] * 0xFFFDFD46 + f[5] * 0xFFFBD6F6 + f[2] * 0x13A87 + f[3] * 0x42997 + f[4] * 0x244E9 + f[1] * 0x20A60 + f[0] * 0x0C3F6 + f[7] * 0xFFFC0F74 + f[8] * 0xFFFE4DC8 + f[9] * 0xFFFE94DC + f[10] * 0xFFFFECB4 + f[11] * 0xFFFD79C6) & 0xffffffff == 0xFEAFEC1F)
solver.add((f[6] * 0xFFFE7848 + f[5] * 0x23EE3 + f[2] * 0xFFFCBAB4 + f[3] * 0x27C92 + f[4] * 0xFFFBFD5C + f[1] * 0xFFFD30C3 + f[0] * 0x5009 + f[7] * 0xFFFE93F1 + f[8] * 0xFFFDE3F3 + f[9] * 0x228DC + f[10] * 0x25EE + f[11] * 0xF242 + f[12] * 0x1160E) & 0xffffffff == 0xFE20EC14)
solver.add((f[6] * 0x648B + f[5] * 0xFFFCF002 + f[2] * 0xFFFE2E15 + f[3] * 0x1E041 + f[4] * 0x594B + f[1] * 0xFFFF3713 + f[0] * 0xFFFED96C + f[7] * 0x1C620 + f[8] * 0xFFFF282A + f[9] * 0xFFFF0E48 + f[10] * 0xFFFEAC54 + f[11] * 0xEA5F + f[12] * 0x35CF4 + f[13] * 0xFFFC920E) & 0xffffffff == 0xFDCA76A0)
solver.add((f[6] * 0x107E1 + f[5] * 0x440D9 + f[2] * 0xFFFFF5C3 + f[3] * 0x30766 + f[4] * 0x21281 + f[1] * 0x235C2 + f[0] * 0x1B2CE + f[7] * 0x16687 + f[8] * 0x493EC + f[9] * 0x26716 + f[0xA] * 0xFFFC84CB + f[0xB] * 0xFFFEA6FA + f[0xC] * 0xFFFC2F98 + f[0xD] * 0xFFFD1A3E + f[0xE] * 0x390BF) & 0xffffffff == 0x5920B01)
solver.add((f[6] * 0x24225 + f[5] * 0xFFFD39FC + f[2] * 0x1EAE2 + f[3] * 0x2F613 + f[4] * 0xFFFC66F9 + f[1] * 0xFFFE0433 + f[0] * 0x3E19 + f[7] * 0x1BDFF + f[8] * 0xFFFC6EAB + f[9] * 0xFFFD810C + f[0xA] * 0x0D519 + f[0xB] * 0x384EC + f[0xC] * 0x197E5 + f[0xD] * 0xFFFFD159 + f[0xE] * 0xFFFF43D9 + f[0xF] * 0xFFFC28DF) & 0xffffffff == 0xFDD0E812)
solver.add((f[6] * 0x111A3 + f[5] * 0xFFFF32EB + f[2] * 0x3E3F9 + f[3] * 0xFFFE9E4B + f[4] * 0xFFFFFB1A + f[1] * 0xFFFF65B9 + f[0] * 0xFFFDF970 + f[7] * 0xFFFB936C + f[8] * 0xFFFEF482 + f[9] * 0x57B6 + f[0xA] * 0x8813 + f[0xB] * 0x25CDC + f[0xC] * 0x12190 + f[0xD] * 0x427BE + f[0xE] * 0xFFFC8358 + f[0xF] * 0xFFFCE4EE + f[0x10] * 0x43BB5) & 0xffffffff == 0xFF9ADC73)
solver.add((f[6] * 0xFFFC313D + f[5] * 0x1023B + f[2] * 0x2E27A + f[3] * 0xFFFDCCD4 + f[4] * 0xFFFE498F + f[1] * 0xFFFFEC0D + f[0] * 0x3A1A3 + f[7] * 0xFFFCC8E2 + f[8] * 0xFFFC37B6 + f[9] * 0xFFFF2FE9 + f[0xA] * 0xFFFE8E68 + f[0xB] * 0x1F45C + f[0xC] * 0xFFFEAC48 + f[0xD] * 0xFFFDBD08 + f[0xE] * 0x2A28 + f[0xF] * 0xD72D + f[0x10] * 0xFFFF70B8 + f[0x11] * 0xFFFFE90F) & 0xffffffff == 0xFCD6008F)
solver.add((f[6] * 0xFFFBB7A0 + f[5] * 0xFFFF0015 + f[2] * 0xFFFD2918 + f[3] * 0x1882D + f[4] * 0xFFFEDE1F + f[1] * 0x2FB77 + f[0] * 0x20D94 + f[7] * 0x14A94 + f[8] * 0xFFFDA0CD + f[9] * 0xDE69 + f[0xA] * 0x2FE8 + f[0xB] * 0x2ABE5 + f[0xC] * 0x26530 + f[0xD] * 0x4C3D + f[0xE] * 0x2383E + f[0xF] * 0x42763 + f[0x10] * 0xE5C9 + f[0x11] * 0x539 + f[0x12] * 0xFFFC5AF3) & 0xffffffff == 0x39F3331)
solver.add((f[6] * 0xFFFD67BD + f[5] * 0xFFFCFC61 + f[2] * 0x21FB1 + f[3] * 0x2AFE7 + f[4] * 0xFFFE2316 + f[1] * 0xFFFDE3DE + f[0] * 0xFFFCF431 + f[7] * 0xFFFF1A07 + f[8] * 0xFFFD1877 + f[9] * 0xFFFBAB46 + f[0xA] * 0xFFFFB7A8 + f[0xB] * 0x44C76 + f[0xC] * 0x3C062 + f[0xD] * 0x26DA8 + f[0xE] * 0x217FE + f[0xF] * 0x27911 + f[0x10] * 0xD484 + f[0x11] * 0x217F6 + f[0x12] * 0xFFFF711C + f[0x13] * 0xFFFE6835) & 0xffffffff == 0x4AF658)
solver.add((f[6] * 0x6C67 + f[5] * 0x4210C + f[2] * 0x24372 + f[3] * 0xFFFF64A1 + f[4] * 0xFFFE83FC + f[1] * 0xFFFC59E3 + f[0] * 0x1A675 + f[7] * 0x29403 + f[8] * 0x122E6 + f[9] * 0x479E1 + f[0xA] * 0xFFFE556B + f[0xB] * 0xFFFEE2E8 + f[0xC] * 0xFFFD0C98 + f[0xD] * 0xF761 + f[0xE] * 0xFFFCF4FD + f[0xF] * 0x24A14 + f[0x10] * 0x2C39B + f[0x11] * 0xFFFF914F + f[0x12] * 0x94F9 + f[0x13] * 0x1F3A9 + f[0x14] * 0xFFFD85A7) & 0xffffffff == 0x2B77651)
solver.add((f[6] * 0x0B245 + f[5] * 0x47951 + f[2] * 0x3C177 + f[3] * 0x2026C + f[4] * 0x2BD3A + f[1] * 0x0AE83 + f[0] * 0xFFFF67E2 + f[7] * 0x0FC81 + f[8] * 0xFFFD1DCD + f[9] * 0xFFFE7D87 + f[0xA] * 0x40428 + f[0xB] * 0x1AC25 + f[0xC] * 0x47B95 + f[0xD] * 0xFFFBD35D + f[0xE] * 0xFFFD55C5 + f[0xF] * 0x255EF + f[0x10] * 0xFFFCA285 + f[0x11] * 0x1B4F2 + f[0x12] * 0xFFFBA306 + f[0x13] * 0x3B929 + f[0x14] * 0xEC4C+f[0x15]*0xFFFCD49C) & 0xffffffff == 0x49F26C9)
while solver.check() == sat:
flag = ""
model = solver.model()
for i in range(len(f)):
flag += chr(model[f[i]].as_long())
print(flag)
solver.add(RecurOr(f, model))
# flag{g0_Fuck_xx_5egm3n

根据题目描述,先做这个热热身,做完这个再去做xx_segment_obf也不迟,猜测flag为

1
flag{g0_Fuck_xx_5egm3nt_0bf}

提交成功

imitation_game

运行程序,首先输出flag提示,flag有两部分,先过第一部分才会运行第二部分的程序

调试程序,调试过程中发现AES的s-box,发现输入了明文之后在后面pad了32位\x1a,然后进行AES-CBC加密,密钥和iv还有最终运行的结果可以在内存里找到,直接解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

def add_to_16(text):
if len(text.encode('utf-8')) % 16:
add = 16 - (len(text.encode('utf-8')) % 16)
else:
add = 0
text = text + ('\0' * add)
return text.encode('utf-8')

def encrypt(text):
key = b"\x3E\x2C\x25\x13\x18\xBE\xC3\x6B\xA1\x37\x24\x53\x03\x1E\x51\xEC"
iv = b"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"
mode = AES.MODE_CBC
text = add_to_16(text)
cryptos = AES.new(key, mode, iv)
cipher_text = cryptos.encrypt(text)
return b2a_hex(cipher_text)

def decrypt(text):
key = b"\x3E\x2C\x25\x13\x18\xBE\xC3\x6B\xA1\x37\x24\x53\x03\x1E\x51\xEC"
iv = b"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"
mode = AES.MODE_CBC
cryptos = AES.new(key, mode, iv)
plain_text = cryptos.decrypt(a2b_hex(text))
return plain_text

if __name__ == '__main__':
e = encrypt("6c8f1d78770fe672122478c6f9a150e8\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a")
d = decrypt(b"9D7BA23CB1099A4841D16663D6AE3CAB87ED59C2D3DA2A05BA5129C15D426A9A0514DBBEAE838B6FD3594152344E39C566E1E3EC0618149F4EB770009077D8AE")
print("加密:", e)
print("解密:", d)

# 6c8f1d78770fe672122478c6f9a150e8

得到第一部分flag,进入第二部分,调用了game.bin文件,根据提示是一个chip8的模拟器,一共输入10位数,错误则提示dead

有了提示之后好做了很多,根据chip8的指令集解析一下game.bin文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
with open('game.txt', 'r+') as f:
s = f.read()
# print(s)
j = 0
for i in range(0, len(s), 5):
t = s[i:i + 4]
# print(t)
print("addr:" + hex(j + 0x200), end=" ")
j += 2
if t[0] == '0':
if t[1] == '0' and t[2] == 'e':
if t[3] == '1':
print("clear screen")
elif t[3] == 'f':
print("Returns from a subroutine")
else:
print("call program at addr: " + t[1:])
else:
print("call program at addr: " + t[1:])
elif t[0] == '1':
print("jmp " + t[1:])
elif t[0] == '2':
print("call " + t[1:])
elif t[0] == '3':
print("Skips the next instruction if V" + t[1] + " equals " + t[2:])
elif t[0] == '4':
print("Skips the next instruction if V" + t[1] + " not equals " + t[2:])
elif t[0] == '5':
print("Skips the next instruction if V" + t[1] + " equals V" + t[2])
elif t[0] == '6':
print("V" + t[1] + " = " + t[2:])
elif t[0] == '7':
print("V" + t[1] + " += " + t[2:])
elif t[0] == '8':
VX = "V" + t[1]
VY = "V" + t[2]
if t[-1] == '0':
print(VX + " = " + VY)
elif t[-1] == '1':
print(VX + " = " + VX + " | " + VY)
elif t[-1] == '2':
print(VX + " = " + VX + " & " + VY)
elif t[-1] == '3':
print(VX + " = " + VX + " ^ " + VY)
elif t[-1] == '4':
print(VX + " += " + VY, " set VF=1 if VX>=255")
elif t[-1] == '5':
print(VX + " -= " + VY, " set VF=0 if VX<=0")
elif t[-1] == '6':
print(VX + " >>= 1", " the last one to VF")
elif t[-1] == '7':
print(VX + " = " + VY + " - " + VX, " set VF=0 if VX&lt;0")
elif t[-1] == 'e':
print(VX + " <<= 1", " the first one to VF")
else:
print("Invalid instruction: " + t)
elif t[0] == '9':
print("Skips the next instruction if V" + t[1] + " not equals V" + t[2])
elif t[0] == 'a':
print("set I = " + t[1:])
elif t[0] == 'b':
print("jmp V0+" + t[1:])
elif t[0] == 'c':
print("V" + t[1] + "=rand()&" + t[2:])
elif t[0] == 'd':
print("display at (V" + t[1] + "," + "V" + t[2] + ") for " + t[3] + "rows")
elif t[0] == 'e':
print("something about buttons")
elif t[0] == 'f':
if t[2:] == '29':
print("set I=" + "V" + t[1])
elif t[2:] == "0a":
print("set V" + t[1] + " = button pressed")
elif t[2:] == "55":
print("store V0-V" + t[1] + " to addr start at I")
elif t[2:] == "65":
print("store addr start at I to V0-V" + t[1])
elif t[2:] == "33":
print("set BCD(V" + t[1] + ")")
else:
print(t[2:])
else:
print("Invalid instruction: " + t)

解析之后根据程序的运行流程看一下大概过程,读取按键在屏幕上指定位置显示出来,直到10位都读取完,然后进行一些判断,错误就会显示dead,正确直接退出程序,不会有显示。然后详细看一下程序

程序开始一个跳转从2ce开始,根据chip8内存的排布规律,可执行代码从200开始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
addr:0x2ce   Ve = 10
addr:0x2d0 set I=Ve
addr:0x2d2 store V0-Ve to addr start at I
addr:0x2d4 Vf = 03
addr:0x2d6 Ve += Vf set VF=1 if VX>=255
addr:0x2d8 call 928
addr:0x2da V0 = Vf
addr:0x2dc V1 = 05
addr:0x2de V2 = 08
addr:0x2e0 V3 = V0
addr:0x2e2 set I=Ve
addr:0x2e4 store V0-Ve to addr start at I
addr:0x2e6 Vf = 03
addr:0x2e8 Ve += Vf set VF=1 if VX>=255
addr:0x2ea V0 = V1
addr:0x2ec V1 = V2
addr:0x2ee V2 = V3
addr:0x2f0 call 938

首先是10个这样的过程用于输入和显示

其中928用于读取输入,记录按键信息

1
2
3
4
5
6
7
8
addr:0x928   V0 = ff
addr:0x92a set V0 = button pressed
addr:0x92c Vf = 03
addr:0x92e Ve -= Vf set VF=0 if VX<=0
addr:0x930 Vf = V0
addr:0x932 set I=Ve
addr:0x934 store addr start at I to V0-Ve
addr:0x936 Returns from a subroutine

938用于输出到显示屏上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
addr:0x938   V5 = V2
addr:0x93a V4 = V1
addr:0x93c V3 = V0
addr:0x93e V6 = 00
addr:0x940 set BCD(V5)
addr:0x942 store addr start at I to V0-V2
addr:0x944 set I=V5
addr:0x946 display at (V3,V4) for 5rows
addr:0x948 V6 = V6 | Vf
addr:0x94a Vf = 03
addr:0x94c Ve -= Vf set VF=0 if VX&lt;0
addr:0x94e Vf = V6
addr:0x950 set I=Ve
addr:0x952 store addr start at I to V0-Ve
addr:0x954 Returns from a subroutine

经过10次这样的操作之后,显示屏上显示出10个输入的数,分别存储在寄存器V0到V9中,接下来对这些输入的数值进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
addr:0x436   Va = Vf
addr:0x438 Va = V0
addr:0x43a Vb = V0
addr:0x43c Vc = 02
addr:0x43e Vb += Vc set VF=1 if VX>=255
addr:0x440 Va = Vb
addr:0x442 V0 = Va
addr:0x444 Va = V1
addr:0x446 Vb = V1
addr:0x448 Vc = 01
addr:0x44a Vb += Vc set VF=1 if VX>=255
addr:0x44c Va = Vb
addr:0x44e V1 = Va
addr:0x450 Va = V2
addr:0x452 Vb = V2
addr:0x454 Vc = 01
addr:0x456 Vb += Vc set VF=1 if VX>=255
addr:0x458 Vc = 01
addr:0x45a Vb = Vb ^ Vc
addr:0x45c Va = Vb
addr:0x45e V2 = Va
addr:0x460 Va = V3
addr:0x462 Vb = V3
addr:0x464 Vc = 03
addr:0x466 Vb += Vc set VF=1 if VX>=255
addr:0x468 Va = Vb
addr:0x46a V3 = Va
addr:0x46c Va = V4
addr:0x46e Vb = V4
addr:0x470 Vc = 02
addr:0x472 Vb += Vc set VF=1 if VX>=255
addr:0x474 Va = Vb
addr:0x476 V4 = Va
addr:0x478 Va = V5
addr:0x47a Vb = V5
addr:0x47c Vc = 02
addr:0x47e Vb = Vb ^ Vc
addr:0x480 Vc = 01
addr:0x482 Vb += Vc set VF=1 if VX>=255
addr:0x484 Va = Vb
addr:0x486 V5 = Va
addr:0x488 Va = V6
addr:0x48a Vb = V6
addr:0x48c Vc = V6
addr:0x48e Vb += Vc set VF=1 if VX>=255
addr:0x490 Va = Vb
addr:0x492 V6 = Va
addr:0x494 Va = V7
addr:0x496 Vb = V7
addr:0x498 Vc = 01
addr:0x49a Vb += Vc set VF=1 if VX>=255
addr:0x49c Va = Vb
addr:0x49e V7 = Va
addr:0x4a0 Va = V8
addr:0x4a2 Vb = V8
addr:0x4a4 Vc = 01
addr:0x4a6 Vb = Vb ^ Vc
addr:0x4a8 Vc = 01
addr:0x4aa Vb += Vc set VF=1 if VX>=255
addr:0x4ac Va = Vb
addr:0x4ae V8 = Va
addr:0x4b0 Va = V9
addr:0x4b2 Vb = V9
addr:0x4b4 Vc = 02
addr:0x4b6 Vb += Vc set VF=1 if VX>=255
addr:0x4b8 Va = Vb
addr:0x4ba V9 = Va

就是如下操作

1
2
3
4
5
6
7
8
9
10
f[0]+=2
f[1]+=1
f[2]=(f[2]+1)^1
f[3]+=3
f[4]+=2
f[5]=(f[5]^2)+1
f[6]=2*f[6]
f[7]+=1
f[8]=(f[8]^1)+1
f[9]+=2

接下来是10个方程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
addr:0x4bc   Va = 00
addr:0x4be Vb = Va
addr:0x4c0 Vc = V0
addr:0x4c2 Vd = 01
addr:0x4c4 set I=Ve
addr:0x4c6 store V0-Ve to addr start at I
addr:0x4c8 Vf = 03
addr:0x4ca Ve += Vf set VF=1 if VX>=255
addr:0x4cc V0 = Vc
addr:0x4ce V1 = Vd
addr:0x4d0 call 27a
addr:0x4d2 Vc = Vf
addr:0x4d4 Vb += Vc set VF=1 if VX>=255
addr:0x4d6 Va = Vb
addr:0x4d8 Vb = Va
addr:0x4da Vc = V1
addr:0x4dc Vd = 02
addr:0x4de set I=Ve
addr:0x4e0 store V0-Ve to addr start at I
addr:0x4e2 Vf = 03
addr:0x4e4 Ve += Vf set VF=1 if VX>=255
addr:0x4e6 V0 = Vc
addr:0x4e8 V1 = Vd
addr:0x4ea call 27a
addr:0x4ec Vc = Vf
addr:0x4ee Vb += Vc set VF=1 if VX>=255
addr:0x4f0 Va = Vb
addr:0x4f2 Vb = Va
addr:0x4f4 Vc = V2
addr:0x4f6 Vd = 01
addr:0x4f8 set I=Ve
addr:0x4fa store V0-Ve to addr start at I
addr:0x4fc Vf = 03
addr:0x4fe Ve += Vf set VF=1 if VX>=255
addr:0x500 V0 = Vc
addr:0x502 V1 = Vd
addr:0x504 call 27a
addr:0x506 Vc = Vf
addr:0x508 Vb += Vc set VF=1 if VX>=255
addr:0x50a Va = Vb
addr:0x50c Vb = Va
addr:0x50e Vc = 21
addr:0x510 Vf = 00
addr:0x512 Skips the next instruction if Vb equals Vc
addr:0x514 Vf = 01
addr:0x516 Vb = Vf
addr:0x518 Skips the next instruction if Vb not equals 00
addr:0x51a jmp 52e
addr:0x51c clear screen
addr:0x51e Vb = Vf
addr:0x520 set I=Ve
addr:0x522 store V0-Ve to addr start at I
addr:0x524 Vf = 03
addr:0x526 Ve += Vf set VF=1 if VX>=255
addr:0x528 call 202

202函数为输出dead函数,需要跳过,传入27a中寄存器Vd的值表示多项式前该项的系数,三个三个一组可以列出10个方程,写脚本z3求解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from z3 import *

def RecurOr(flags, models, pos=0):
if pos <= len(flags) - 1:
return Or(models[flags[pos]] != flags[pos], RecurOr(flags, models, pos + 1))
else:
return Or(models[flags[pos]] != flags[pos])

f = [Int('v%d' % i) for i in range(9)]
flag = []
solver = Solver()

for c in f:
solver.add(c >= 0x0)
solver.add(c <= 0xff)

solver.add(f[0] + 2 * f[1] + f[2] == 0x21)
solver.add(2 * f[0] + f[1] + f[2] == 0x2a)
solver.add(f[0] + 2 * f[1] + 2 * f[2] == 0x30)
solver.add(f[3] + 2 * f[4] + f[5] == 0x37)
solver.add(2 * f[3] + f[4] + f[5] == 0x37)
solver.add(f[3] + 2 * f[4] + 2 * f[5] == 0x3b)
solver.add(f[6] + 2 * f[7] + f[8] == 0x1f)
solver.add(2 * f[6] + f[7] + f[8] == 0x16)
solver.add(f[6] + 2 * f[7] + 2 * f[8] == 0x20)

while solver.check() == sat:
model = solver.model()
ff = [model[f[0]].as_long() - 2, model[f[1]].as_long() - 1, (model[f[2]].as_long() ^ 1) - 1,
model[f[3]].as_long() - 3, model[f[4]].as_long() - 2, (model[f[5]].as_long() - 1) ^ 2,
model[f[6]].as_long() // 2, model[f[7]].as_long() - 1, (model[f[8]].as_long() - 1) ^ 1, 5 - 2]

print(ff)
solver.add(RecurOr(f, model))
# a2def12c13

两部分都得到,拼起来提交正确

1
flag{6c8f1d78770fe672122478c6f9a150e8a2def12c13}
2020-钓鱼城杯-wp 2020-信息安全竞赛创新实践赛-wp

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×