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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
import random
random.seed(133713371337)
asm = """
not r0
mov r0, r2
ldb r0, r3 # lsfr
jnz chk_loop
lsfr_advance:
# bit 0
mov r3, r0
shr r3, 1
shl r0, 7
xor r0, r3
# bit 3
mov r3, r0
shr r0, 2
shl r0, 7
xor r0, r3
# bit 6
mov r3, r0
shr r0, 5
shl r0, 7
xor r0, r3
# if != 0, jmp, else
# fallthrough to same location
jnz lsfr_advance_ret
chk_loop:
jnz lsfr_advance
lsfr_advance_ret:
xor r0, r0
not r0
shr r0, 3
and r3, r0
xor r1, r1
inc r1
shl r1, 7
add r1, r0
ldb r0, r1
jnz check_val
check_val_ret:
mov r1, r0
jnz chk_loop
not r0
jnz end1
check_val:
inp r0
xor r3, r1
xor r0, r1
not r1
and r1, r2
mov r0, r1
xor r0, r0
not r0
jnz check_val2
check_val2_ret:
jnz check_val_ret
end1:
jnz end2
check_val2:
xor r0, r0
inc r0
shl r0, 2
inc r0
shl r0, 1
xor r0, r1
jnz check_val2_ret
end2:
mov r2, r0
not r0
jnz print_fail
not r0
jnz print_ok
print_fail:
xor r2, r2
not r2
shl r2, 3
jnz print
print_ok:
xor r2, r2
not r2
shl r2, 4
print:
xor r1, r1
inc r1
print_loop:
ldb r2, r0
jnz print_cont
hlt
print_cont:
out r0
add r1, r2
jnz print_loop
"""
flag = b"ALLES!{T3553L4T3!}\x0a"
data = {}
# ensure lsfr hits different indexes
seed_ok = False
lsfr_init = None
for lsfr_init in range(0x6f, 256):
reg = lsfr_init
data.clear()
seed_ok = True
vals = []
for i,c in enumerate(flag):
b = (reg >> 6) & 0x01
b ^= (reg >> 3) & 0x01
b ^= (reg >> 0) & 0x01
reg = (b << 7) | (reg >> 1)
vals.append(reg)
addr = 0x80 + (reg & 0x1f)
vals.append(addr)
if addr in data:
seed_ok = False
data[addr] = c ^ reg
if seed_ok:
print("vals", [hex(v) for v in vals])
break
assert(seed_ok)
for i,b in enumerate(b"ok\n\x00"):
data[0xf0+i] = b
for i,b in enumerate(b"fail\n\x00"):
data[0xf8+i] = b
data[0xff] = lsfr_init
bytecode = []
labels = {}
for l in asm.split("\n"):
l = l.replace(",", " ").strip().lower()
if ":" in l:
name = l.split(":")[0]
labels[name] = len(bytecode)
continue
elif l == "" or l.strip().startswith("#"):
continue
cmd, ops = l.split()[0], l.split()[1:3]
if cmd == "jnz":
name, = ops
bytecode.append(name)
elif cmd == "shl":
r1,sh = int(ops[0][1:]), int(ops[1])
assert(r1 >= 0 and r1 < 4)
assert(sh >= 0 and sh < 8)
bytecode.append(0b01000000 | (r1 << 3) | sh)
elif cmd == "shr":
r1,sh = int(ops[0][1:]), int(ops[1])
assert(r1 >= 0 and r1 < 4)
assert(sh >= 0 and sh < 8)
bytecode.append(0b01100000 | (r1 << 3) | sh)
elif cmd == "mov":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b00100000 | (r1 << 2) | r2)
elif cmd == "swp":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b00110000 | (r1 << 2) | r2)
elif cmd == "add":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b10000000 | (r1 << 2) | r2)
elif cmd == "sub":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b10010000 | (r1 << 2) | r2)
elif cmd == "xor":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b10100000 | (r1 << 2) | r2)
elif cmd == "and":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b10110000 | (r1 << 2) | r2)
elif cmd == "ldb":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b11000000 | (r1 << 2) | r2)
elif cmd == "stb":
r1,r2 = [int(o[1:]) for o in ops]
assert(r1 >= 0 and r1 < 4)
assert(r2 >= 0 and r2 < 4)
bytecode.append(0b11010000 | (r1 << 2) | r2)
elif cmd == "inp":
reg, = [int(o[1:]) for o in ops]
assert(reg >= 0 and reg < 4)
bytecode.append(0b11100000 | reg)
elif cmd == "out":
reg, = [int(o[1:]) for o in ops]
assert(reg >= 0 and reg < 4)
bytecode.append(0b11100100 | reg)
elif cmd == "not":
reg, = [int(o[1:]) for o in ops]
assert(reg >= 0 and reg < 4)
bytecode.append(0b11101000 | reg)
elif cmd == "inc":
reg, = [int(o[1:]) for o in ops]
assert(reg >= 0 and reg < 4)
bytecode.append(0b11110000 | reg)
#elif cmd == "dec":
# reg, = [int(o[1:]) for o in ops]
# assert(reg >= 0 and reg < 4)
# bytecode.append(0b11110100 | reg)
elif cmd == "hlt":
bytecode.append(0b11111111)
else:
print(cmd)
assert(False)
for i,b in enumerate(bytecode):
if type(b) == str:
off = labels[b] - (i + 1) + 16
print(b, off)
assert(off >= 0 and off < 32)
bytecode[i] = 0b00000000 | off
print(len(bytecode), bytecode)
bytecode += random.randbytes(0x100 - len(bytecode))
for p,v in data.items():
bytecode[p] = v
for i in range(4):
with open(f"build/memory{i+1}.bin", "wb+") as f:
f.write(bytes(bytecode[i*64:i*64+64]))
|