-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate_solutions.py
executable file
·462 lines (397 loc) · 12.9 KB
/
create_solutions.py
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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
#!/usr/bin/env python
from keystone import *
import struct
import itertools
import math
KS = Ks(KS_ARCH_X86, KS_MODE_64)
ROP_AREA_START = 0x00800000
COMPUTING_STACK_START = 0x30000000
COMPUTING_HEAP_START = 0x40000000
OUTPUT_AREA = 0x50000000
# memory layout in HEAP_START: move, tick, pad(0x100), state with polar per team
def g(value, ending="ret"):
valuer = value + "; %s" % ending
encoding, _ = KS.asm(valuer)
assert len(encoding)<=3
penconding = encoding + [0] * (3 - len(encoding))
vv = penconding[0] * pow(2,16) + penconding[1] * pow(2,8) + penconding[2]
return "*rop_ptr = chain_table[%s]; //%s\nrop_ptr++;\n" % (hex(vv), valuer)
def d(value):
return "*rop_ptr = (unsigned long*)%sL;\nrop_ptr++;\n" % hex(value)
def s(value):
return "rop_ptr = (unsigned long**)%sL;\n" % hex(value)
def save_to_team_solution(tstr, defcon_id):
with open("solutions/team"+str(defcon_id)+".c", "r") as fp:
cco = fp.read()
before, token1, after = cco.partition("//#ROPCHAINBUILDER_start")
_, token2, after = after.partition("//#ROPCHAINBUILDER_end")
cc = "\n".join((s.strip() for s in (before, token1, tstr, token2, after)))
with open("solutions/team"+str(defcon_id)+".c", "w") as fp:
fp.write(cc)
def save_extra_to_team_solution(tstr, defcon_id):
with open("solutions/team"+str(defcon_id)+"extra", "wb") as fp:
fp.write(tstr)
def move_list_to_solution(mlist):
tstr = ""
#tstr += g("jmp 0")
tstr += g("pop rcx")
tstr += d(COMPUTING_HEAP_START)
tstr += g("pop rsi")
tstr += d(COMPUTING_HEAP_START+8)
tstr += g("pop rbx")
tstr += d(0x0) #this is the 2-days bug, only needed if registers are not cleared
tstr += g("mov bl, byte ptr [rsi]")
tstr += g("inc esi")
tstr += g("mov bh, byte ptr [rsi]")
tstr += g("shl ebx")
tstr += g("shl ebx")
tstr += g("shl ebx")
tstr += g("shl ebx")
tstr += g("shl ebx")
tstr += g("shl ebx")
tstr += g("shl ebx")
tstr += g("shl ebx") #0x100
tstr += g("pop rax")
tstr += d(COMPUTING_STACK_START+0x100)
tstr += g("add eax, ebx")
tstr += g("mov esp, eax")
for i, m in enumerate(mlist):
tstr += s(OUTPUT_AREA+0x100+(0x100*i))
tstr += g("pop rdx")
if m == "X":
tstr += g("pop rcx")
tstr += d(0x13)
tstr += g("mov byte ptr [rcx], dl")
else:
tstr += d(ord(m))
tstr += g("mov byte ptr [rcx], dl")
tstr += g("jmp 0")
return tstr
def create_move_table(mx=64*2,my=64*2,ma=128,sx=16,sy=16,sa=4,arange=3.8,adistance=110.0):
def twos_comp(val, bits=11):
"""compute the 2's complement of int value val"""
if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
val = val - (1 << bits) # compute negative value
return val
pmtable = [ord(b"s")] * (mx*my*ma)
for idx, (x, y, a) in enumerate(itertools.product(range(mx), range(my), range(ma))):
if x == mx-1: # max value
# who we want to attack is not existing --> s
# this does not really work, because 0xffff is subtracted to another value, I now check explicitly for NULL ship
continue
if x == 0 and y == 0:
# who we want to attack is ourself --> s
continue
rx = twos_comp(x*sx)
ry = twos_comp(y*sy)
ra = (a*sa)%360.0
absangle = (math.atan2(ry, rx) / math.pi * 180.0)%360.0
dangle = (absangle-ra)%360
#print(dangle)
if dangle < arange or dangle > (360.0-arange):
if math.sqrt(rx*rx+ry*ry) > adistance:
pmtable[x*my*ma+y*ma+a] = ord(b"u")
else:
pmtable[x*my*ma+y*ma+a] = ord(b"a")
else:
if dangle <=180.0:
pmtable[x*my*ma+y*ma+a] = ord(b"l")
else:
pmtable[x*my*ma+y*ma+a] = ord(b"r")
#pmtable = pmtable[:10000]
tstr = b"\x48\xc7\xc0\x00\x00\x10\x50"
tstr += b"".join((b"\xc6\x00" + (chr(c)).encode("utf-8") + b"\x48\xff\xc0" for c in pmtable))
#tstr += "unsigned char table[] = {%s};\n" % ",".join([r"'%s'"%chr(c) for c in pmtable])
return tstr
'''
tstr = ""
tstr += g("pop rcx")
tstr += d(COMPUTING_HEAP_START)
tstr += g("pop rdx")
tstr += d(ord(b"r"))
tstr += g("mov byte ptr [rcx], dl")
#tstr += g("jmp 0")
'''
mlist = (["l"]*10 + ["s", "a"]) + (["d"]*10 + ["r"]*25 + ["d"]*10 + ["a"] + ["u"]*20 + ["l"]*22 + ["a", "s"] ) * 20
save_to_team_solution(move_list_to_solution(mlist), 15)
mlist = mlist[::-1]
save_to_team_solution(move_list_to_solution(mlist), 1)
'''
tstr = ""
tstr += g("pop rax")
tstr += d(0x10)
tstr += g("inc edx")
tstr += g("sub esp, eax")
save_to_team_solution(tstr, 3)
# avg is > 9M instructions with 0.05, 20M with 0.10
'''
#######################################################################3
tstr = ""
tstr += g("pop rsi")
tstr += d(COMPUTING_HEAP_START+8)
tstr += g("mov bl, byte ptr [rsi]")
tstr += g("inc esi")
tstr += g("mov bh, byte ptr [rsi]")
tstr += g("mov esi, ebx") #rsi is the current tick
tstr += g("pop rbx")
tstr += d(0x0)
tstr += g("pop rax") #rdi is team_id
tstr += d(COMPUTING_HEAP_START+16)
tstr += g("mov bl, byte ptr [rax]")
tstr += g("mov edi, ebx")
tstr += (g("shl edi"))*8 #rdi is team_id *0x100
tstr += g("pop rbx")
tstr += d(0x0)
tstr += g("pop rax")
tstr += d(COMPUTING_HEAP_START+0x100+8*5)
tstr += g("add eax, edi") #eax points to .x of our team
# ebx = dword ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += (g("shl ebx"))*16
tstr += g("dec eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += g("inc eax") * 8 # eax points to .y of our team
# ecx = word ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
tstr += (g("shl ecx"))*16
tstr += g("dec eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
#ebx/ecx is our location
tstr += g("inc eax") * 8 # eax points to .a of our team
# ecx = word ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov dh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov dl, byte ptr [rax]")
tstr += (g("shl edx"))*16
tstr += g("dec eax")
tstr += g("mov dh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov dl, byte ptr [rax]")
#edx is our angle
#tstr += g("jmp 0")
#rsi (the tick) is used to select the team to attack, based on %128
tstr += (g("shr esi"))*7
tstr += g("pop rax")
tstr += d(0x000000000000000f) # modulo 0xf
tstr += g("and esi, eax")
#tstr += (g("inc esi"))*3 #attack team tid 3 at the beginning
tstr += (g("shl esi"))*8
tstr += g("pop rax")
tstr += d(COMPUTING_HEAP_START+0x100+8*4)
tstr += g("add eax, esi") #eax points to .x of the to-attack team
# move our location to esi/edi
tstr += g("mov esi, ebx")
tstr += g("mov edi, ecx")
# check for NULL ship
tstr += g("pop rbx")
tstr += d(0x0)
tstr += g("mov bl, byte ptr [rax]")
tstr += (g("shl ebx"))*6 # 8 gadgets skipped (after the next) if bl = 1 (ship is present)
tstr += g("add esp, ebx")
tstr += g("pop rdx")
tstr += d(ord(b's'))
tstr += g("pop rcx")
tstr += d(COMPUTING_HEAP_START)
tstr += g("mov byte ptr [rcx], dl")
tstr += g("jmp 0")
tstr += g("jmp 0")
tstr += g("jmp 0")
tstr += g("inc eax")*8
# ebx = dword ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += (g("shl ebx"))*16
tstr += g("dec eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += g("inc eax") * 8 # eax points to .y of the other team
# ecx = word ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
tstr += (g("shl ecx"))*16
tstr += g("dec eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
#ebx/ecx is the other team location
#subtract locations and scale them
tstr += g("sub ebx, esi")
tstr += g("sub ecx, edi")
tstr += g("mov esi, ebx")
tstr += g("mov edi, ecx")
tstr += g("shr esi") * 4 # 1024 -> 64 (non existing ship distance is 0xff)
tstr += g("shr edi") * 4 # 1024 -> 64
#scale angle
tstr += g("shr edx") * 2
#create table index
tstr += g("pop rax")
tstr += d(0x000000000000007f) #mask: just get 0->64 values with sign
tstr += g("and esi, eax")
tstr += g("shl esi") * 7
tstr += g("and edi, eax")
tstr += g("or esi, edi")
tstr += g("shl esi") * 7
tstr += g("or esi, edx")
# esi is the table index [dx/64, dy/64, my_angle/4]
MOVE_TABLE_OFFSET = 0x100000
MOVE_TABLE_LOCATION = OUTPUT_AREA+MOVE_TABLE_OFFSET
tstr += g("pop rax")
tstr += d(COMPUTING_STACK_START+MOVE_TABLE_OFFSET)
tstr += g("add eax, esi")
tstr += g("pop rbx")
tstr += d(0x0)
tstr += g("mov bl, byte ptr [rax]")
tstr += g("pop rcx")
tstr += d(COMPUTING_HEAP_START)
tstr += g("mov byte ptr [rcx], bl")
#tstr += g("jmp 0")
#tstr += s(MOVE_TABLE_LOCATION)
#tstr += create_move_table()
save_to_team_solution(tstr, 6)
save_extra_to_team_solution(create_move_table(), 6)
#TODO debug on tick > 256
##############################################################
tstr = ""
for i in range(20):
tstr += g("pop rax") #rdi is team_id
tstr += d(COMPUTING_HEAP_START+16)
tstr += g("pop rsi")
tstr += d(0)
tstr += g("pop rdi")
tstr += d(0)
tstr += g("pop rbx")
tstr += d(0)
tstr += g("pop rcx")
tstr += d(0)
tstr += g("pop rdx")
tstr += d(0)
tstr += g("mov bl, byte ptr [rax]")
tstr += g("mov edi, ebx")
tstr += (g("shl edi"))*8 #rdi is team_id *0x100
tstr += g("pop rbx")
tstr += d(0x0)
tstr += g("pop rax")
tstr += d(COMPUTING_HEAP_START+0x100+8*5)
tstr += g("add eax, edi") #eax points to .x of our team
# ebx = dword ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += (g("shl ebx"))*16
tstr += g("dec eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += g("inc eax") * 8 # eax points to .y of our team
# ecx = word ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
tstr += (g("shl ecx"))*16
tstr += g("dec eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
#ebx/ecx is our location
# move our location to esi/edi
tstr += g("mov esi, ebx")
tstr += g("mov edi, ecx")
tstr += g("pop rax")
# we do not check if the bullet exists (so there is always a bullet at 0)
tstr += d(COMPUTING_HEAP_START+0x2000+i*0x30+0x10)
# ebx = dword ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += (g("shl ebx"))*16
tstr += g("dec eax")
tstr += g("mov bh, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov bl, byte ptr [rax]")
tstr += g("inc eax") * 8 # eax points to .y of the bullet
# ecx = word ptr [eax]
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("inc eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
tstr += (g("shl ecx"))*16
tstr += g("dec eax")
tstr += g("mov ch, byte ptr [rax]")
tstr += g("dec eax")
tstr += g("mov cl, byte ptr [rax]")
#ebx/ecx is the bullet
#tstr += g("jmp 0")
tstr += g("sub ebx, esi")
tstr += g("sub ecx, edi")
tstr += g("mov esi, ebx")
tstr += g("mov edi, ecx")
#esi/edi is the difference
tstr += g("mov eax, esi")
tstr += g("imul eax")
tstr += g("mov esi, eax")
tstr += g("mov eax, edi")
tstr += g("imul eax")
tstr += g("mov edi, eax")
tstr += g("add esi, edi") #squared distance
tstr += g("pop rbx")
tstr += d(pow(100,2))
tstr += g("sub esi, ebx") # negative if near
tstr += (g("shr esi"))*31
tstr += g("pop rax")
tstr += d(0x1)
tstr += g("and esi, eax") # esi is 1 if near
tstr += g("not esi")
tstr += g("and esi, eax") # esi is 0 if near
tstr += (g("shl esi"))*6 # 8 gadgets
tstr += g("add esp, esi")
tstr += g("pop rdx")
tstr += d(ord(b's'))
tstr += g("pop rcx")
tstr += d(COMPUTING_HEAP_START)
tstr += g("mov byte ptr [rcx], dl")
tstr += g("jmp 0")
tstr += g("jmp 0")
tstr += g("jmp 0")
tstr += g("pop rdx")
tstr += d(ord(b'l'))
tstr += g("pop rcx")
tstr += d(COMPUTING_HEAP_START)
tstr += g("mov byte ptr [rcx], dl")
save_to_team_solution(tstr, 3)