0%

qwb2022

qwb2022

这次还是很坐牢,但跟师傅们学习到了很多方法

deeprev

我们会发现,这个题给了个libsecret.so文件和deeprev文件,deeprev里很清楚,只要check函数等于0就行,但在程序中根本找不到check函数。经搜索发现是GoogleCTF改编题,直接跑下面脚本,把关于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
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
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
# Author: hgarrereyn
# Desc: Lifter solution for GoogleCTF 2022 eldar

import lief
from collections import namedtuple
from dataclasses import dataclass
from typing import Any
from capstone import *



md = Cs(CS_ARCH_X86, CS_MODE_64)

b = None
try:
b = lief.ELF.parse('./deeprev')
except:
raise Exception('Must have the ./eldar binary in cwd')

rela = [x for x in b.sections if x.name == '.rela.dyn'][0]
print(rela)
dynsym = [x for x in b.sections if x.name == '.dynsym'][0]


@dataclass
class Symbol(object):
idx: int
def __repr__(self):
return f's{self.idx}'

@dataclass
class Reloc(object):
idx: int
def __repr__(self):
return f'r{self.idx}'

@dataclass
class Ref(object):
val: Any
def __repr__(self):
return f'&{self.val}'

@dataclass
class SymAddr(object):
sym: Symbol
field: str
def __repr__(self):
return f'{self.sym}.{self.field}'

@dataclass
class RelocAddr(object):
reloc: Reloc
field: str
def __repr__(self):
return f'{self.reloc}.{self.field}'

def vaddr(self):
off = 0
match self.field:
case 'r_address':off = 0
case 'r_info': off = 8
case 'r_addend': off = 16

return (self.reloc.idx * 24) + off + rela.virtual_address

@dataclass
class FlagAddr(object):
idx: int
def __repr__(self):
return f'flag[{self.idx}]'

@dataclass
class OutAddr(object):
idx: int

def __repr__(self):
return f'out[{self.idx}]'

@dataclass
class ArrAddr(object):
idx: int

def __repr__(self):
return f'arr[{self.idx}]'

BaseAddr = namedtuple('baseaddr', [])
FailAddr = namedtuple('fail', [])

def format_addr(addr: int):
if addr >= rela.virtual_address and addr < rela.virtual_address + rela.size:
offset = addr - rela.virtual_address
r_offset = (offset // 24)
r_rem = offset % 24

if r_offset >= 3 and r_offset <= 88:
arr_idx = (r_offset - 3) * 3 + (r_rem // 8)
return ArrAddr(arr_idx)
elif r_offset == 89:
return OutAddr(r_rem)

match r_rem:
case 0: return RelocAddr(Reloc(r_offset), 'r_address')
case 8: return RelocAddr(Reloc(r_offset), 'r_info')
case 16: return RelocAddr(Reloc(r_offset), 'r_addend')
case _: return RelocAddr(Reloc(r_offset), r_rem)
elif addr > dynsym.virtual_address and addr < dynsym.virtual_address + dynsym.size:
offset = addr - dynsym.virtual_address
r_offset = (offset // 24)
r_rem = offset % 24

match r_rem:
case 0: return SymAddr(Symbol(r_offset), 'st_name')
case 8: return Symbol(r_offset)
case 16: return SymAddr(Symbol(r_offset), 'st_size')
case _: return SymAddr(Symbol(r_offset), r_rem)
elif addr >= 0x404040 and addr < 0x404040+33:
off = addr-0x404040
return FlagAddr(off)
elif addr == 0x804000:
return BaseAddr()
elif addr == 0x404064:
return FailAddr()
else:
return addr

def to_sym(name):
assert len(name) == 1
return Symbol(ord(name[0]))

Rel = namedtuple('REL', ['dst','val','ridx'])
Copy = namedtuple('CPY', ['dst', 'symbol', 'ridx'])
R64 = namedtuple('R64', ['dst','symbol','addend','ridx'])
R32 = namedtuple('R32', ['dst','symbol','addend','ridx'])

def parse(b) -> list:
print('[*] Loading relocations...')
relocs = list(b.relocations)

print('[*] Parsing...')
instructions = []
for i in range(3, len(relocs)):
r = relocs[i]
match r.type:
case 1: # R64
instructions.append(R64(format_addr(r.address), to_sym(r.symbol.name), format_addr(r.addend), i))
case 5: # CPY
instructions.append(Copy(format_addr(r.address), to_sym(r.symbol.name), i))
case 8: # REL
instructions.append(Rel(format_addr(r.address), format_addr(r.addend), i))
case 10: # R32
instructions.append(R32(format_addr(r.address), to_sym(r.symbol.name), format_addr(r.addend), i))

return instructions

Mov = namedtuple('mov', ['dst', 'src', 'sz', 'ridx'])
Add = namedtuple('add', ['dst', 'src', 'addend', 'ridx'])

def lift_mov_add(instructions):
idx = 0

sizes = []
curr = [8] * 8
sizes.append(curr)

for instr in instructions:
c = list(curr)
match instr:
case Rel(SymAddr(Symbol(idx), 'st_size'), val, ridx):
c[idx] = val
sizes.append(c)

while idx < len(instructions):
match instructions[idx]:
case Rel(dst, val, ridx):
instructions[idx] = Mov(dst, Ref(val), 8, ridx)
case Copy(dst, sym, ridx):
instructions[idx] = Mov(dst, sym, sizes[idx][sym.idx], ridx)
case R64(dst, sym, add, ridx):
instructions[idx] = Add(dst, sym, add, ridx)
idx += 1
return instructions

def remove_sizes(instructions):
# Sizes are now nops
idx = 0
while idx < len(instructions):
match instructions[idx]:
case Mov(SymAddr(Symbol(s), 'st_size'), _, _, _) if s != 3:
instructions[idx:idx+1] = []

idx += 1
return instructions

def lift_indirect(instructions):
idx = 0
while idx < len(instructions):
match instructions[idx:idx+3]:
case [
Mov(RelocAddr(Reloc(rel_1), 'r_addend'), Symbol(sidx_1), sz_1, ridx_1),
Add(dst_2, sym_2, _, ridx_2),
Mov(RelocAddr(Reloc(rel_3), 'r_addend'), Ref(0), sz_3, _),
] if (
(rel_1 == ridx_2) and (rel_3 == ridx_2)
):
instructions[idx:idx+3] = [
Add(dst_2, sym_2, Symbol(sidx_1), ridx_1)
]

idx += 1
return instructions

Block = namedtuple('block', ['arr', 'flag', 'ridx'])
Output = namedtuple('output', ['out', 'arr', 'ridx'])

def lift_block(instructions):

idx = 0
while idx < len(instructions):
match instructions[idx:idx+18]:
case [
Mov(_,arr,_,ridx),
Add(_,_,_,_),
Mov(_,flag,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
R32(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
Add(_,_,_,_),
Add(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
]:
instructions[idx:idx+18] = [
Block(arr, flag, ridx)
]
idx += 1
return instructions

Reset = namedtuple('reset', ['ridx'])
ShuffleBlock = namedtuple('shuffleblock', ['f1', 'f2', 'ridx'])

def lift_reset(instructions):
idx = 0
while idx < len(instructions) - 256:
good = True

for i in range(256):
op = instructions[idx+i]
if type(op) == Mov:
dst, src, _, _ = op
if dst != ArrAddr(i) or src != Ref(i):
good = False
break
else:
good = False
break

if good:
instructions[idx:idx+256] = [Reset(instructions[idx].ridx)]

idx += 1
return instructions

def lift_shuffle_block(instructions):
idx = 0
while idx < len(instructions) - 256:
good = True

for i in range(256):
op = instructions[idx+i]
if type(op) == Block:
arr, flag, ridx = op
if arr != Ref(ArrAddr(i)):
good = False
break
else:
good = False
break

if good:
instructions[idx:idx+256] = [ShuffleBlock(instructions[idx].flag, instructions[idx+1].flag, instructions[idx].ridx)]

idx += 1
return instructions

Output = namedtuple('output', ['out', 'arr', 'ridx'])

def lift_output(instructions):
idx = 0
while idx < len(instructions):
match instructions[idx:idx+26]:
case [
Mov(_,arr,_,ridx),
Add(_,_,_,_),
R32(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
Add(_,_,_,_),
Add(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
R32(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
Mov(_,_,_,_),
Add(_,_,_,_),
Add(_,_,_,_),
Add(_,_,_,_),
Mov(out,_,_,_),
]:
instructions[idx:idx+26] = [Output(out, arr, ridx)]
idx += 1
return instructions

MultAdd = namedtuple('multadd', ['out', 'val', 'k', 'ridx'])

def lift_multadd(instructions):
idx = 0
while idx < len(instructions):
match instructions[idx:idx+3]:
# block prefix
case [
Mov(Symbol(2), out, _, ridx),
Mov(Symbol(5), Symbol(2), _, _),
Mov(Symbol(6), Ref(0), _, _),
]:
k = 0
double = False

ptr = idx + 3

good = True
while ptr < len(instructions):
match instructions[ptr]:
case Mov(Symbol(2), Ref(Symbol(6)), _, _):
double = True
case Mov(Symbol(2), Ref(Symbol(5)), _, _):
double = False
case Add(Symbol(6), Symbol(6), Symbol(2), _):
k = (k * 2) if double else (k + 1)
case Add(Symbol(7), Symbol(7), Symbol(2), _):
ptr += 1
break
case _:
good = False
break

ptr += 1

if good:
instructions[idx:ptr] = [
MultAdd(Symbol(7), out, k, ridx)
]

idx += 1

return instructions

Trunc = namedtuple('trunc', ['val', 'k', 'ridx'])

def lift_truncate(instructions):
idx = 0
while idx < len(instructions):
match instructions[idx:idx+2]:
case [
Mov(Symbol(2), Ref(SymAddr(Symbol(5), 11)), _, ridx),
Mov(SymAddr(Symbol(7), 11), Symbol(2), 5, _)
]:
instructions[idx:idx+2] = [
Trunc(Symbol(7), 0xffffff, ridx)]
idx += 1
return instructions

ArraySlots = namedtuple('arr', ['values', 'ridx'])

def lift_array_slots(instructions):
idx = 0

while idx < len(instructions):
match instructions[idx]:
case Mov(BaseAddr(), Ref(0), _, ridx):
ptr = idx+1
while ptr < len(instructions):
op = instructions[ptr]
if type(op) != Mov or op.dst != BaseAddr():
break
ptr += 1

start = idx
end = ptr

data = []

# Check for movs into array.
vstart = RelocAddr(Reloc(ridx), 'r_address').vaddr()
offset = 0
while end + offset < len(instructions) and offset < ((end - start) * 3):
op = instructions[end + offset]
if type(op) == Mov and type(op.dst) is RelocAddr and op.dst.vaddr() == vstart + (offset * 8):
data.append(op.src.val)
else:
break
offset += 1

if len(data) > 0:
data += [0] * (((end - start) * 3) - len(data))
instructions[idx:end+offset] = [
ArraySlots(data, ridx)
]

idx += 1
return instructions

Shellcode = namedtuple('shellcode', ['dst', 'code', 'ridx'])

def lift_shellcode(instructions):
idx = 0
while idx < len(instructions):
match instructions[idx:idx+6]:
case [
ArraySlots(values, ridx),
Mov(Symbol(3), Ref(RelocAddr(Reloc(rel2), 'r_address')), _, _),
Mov(SymAddr(Symbol(3), 'st_name'), _, _, _),
Add(dst, Symbol(3), _, _),
Mov(Symbol(2), _, _, _),
Mov(RelocAddr(Reloc(rel6), 'r_address'), Symbol(2), _, _)
] if (rel2 == ridx) and (rel6 == ridx):
instructions[idx:idx+6] = [
Shellcode(dst, b''.join([(x & 0xffffffffffffffff).to_bytes(8, 'little') for x in values]), ridx)
]
idx += 1
return instructions

Aop = namedtuple('aop', ['dst', 'op', 'val', 'k', 'ridx'])

def lift_aop(instructions):
idx = 0
while idx < len(instructions):
match instructions[idx:idx+5]:
case [
Mov(Symbol(2), val, _, ridx),
Mov(Symbol(5), Symbol(2), _, _),
Shellcode(_, data, _),
Mov(Symbol(2), Ref(Symbol(5)), _, _),
Add(dst, dst2, Symbol(2), _)
] if len(data) == 24 and (dst == dst2):
op = next(md.disasm(data, 0))

t = op.mnemonic
k = int(op.op_str.split(', ')[-1], 16)

instructions[idx:idx+5] = [
Aop(dst, t, val, k, ridx)
]

idx += 1
return instructions






def dump(instructions):
for op in instructions:
match op:
case Mov(SymAddr(sym, 'st_name'), Ref(val), 8, ridx) if type(val) is int:
name = val & 0xffffffff
info = (val >> 4) & 0xff
other = (val >> 5) & 0xff
shndx = (val >> 6) & 0xffff
print(f'[{ridx:04d}] :: setinfo {sym}, name=0x{name:x}, info=0x{info:x}, other=0x{other:x}, shndx=0x{shndx:x}')
case Mov(BaseAddr(), Ref(0), _, ridx):
print(f'[{ridx:04d}] :: [ARRAY SLOT]')
case Mov(dst, src, 8, ridx):
print(f'[{ridx:04d}] :: mov {dst}, {src}')
case Mov(dst, src, sz, ridx):
print(f'[{ridx:04d}] :: mov({sz}) {dst}, {src}')
case Add(dst, src, add, ridx):
print(f'[{ridx:04d}] :: add {dst}, {src}, {add}')
case R32(dst, src, add, ridx):
print(f'[{ridx:04d}] :: r32 {dst}, {src}, {add}')
case Block(arr, flag, ridx):
print(f'[{ridx:04d}] :: shuffle {arr}, {flag}')
case Output(out, arr, ridx):
print(f'[{ridx:04d}] :: output {out}, {arr}')
case ShuffleBlock(f1, f2, ridx):
print(f'[{ridx:04d}] :: shuffleblock {f1}, {f2}')
case MultAdd(dst, val, k, ridx):
print(f'[{ridx:04d}] :: madd {dst} += ({val} * {k})')
case Aop(dst, op, val, k, ridx):
print(f'[{ridx:04d}] :: aop {dst} += ({val} {op} {k})')
case Reset(ridx):
print(f'[{ridx:04d}] :: reset')
case Trunc(val, k, ridx):
print(f'[{ridx:04d}] :: trunc {val} &= 0x{k:x}')
case ArraySlots(values, ridx):
print(f'[{ridx:04d}] :: array [{", ".join([hex(x) for x in values])}]')
case Shellcode(dst, code, ridx):
print(f'[{ridx:04d}] :: exec {dst} <- {code.hex()}')
print('-' * 20)
for i in md.disasm(code, 0):
if i.mnemonic == 'ret':
break
print(" 0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str.replace('0x8040e4', 's5').replace('0x8040cc', 's4')))
print('-' * 20)
case _:
print(op)

LIFTS = [
lift_mov_add,
remove_sizes,
lift_indirect,
lift_block,
lift_reset,
lift_shuffle_block,
lift_output,
lift_multadd,
lift_truncate,
lift_array_slots,
lift_shellcode,
lift_aop,
]

def lift(instructions):
for lift_fn in LIFTS:
print(f'[*] {lift_fn.__name__}...')
instructions = lift_fn(instructions)
return instructions

instructions = parse(b)
instructions = lift(instructions)
dump(instructions)

然后得到下面的类似汇编,甚至还有机器码。

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
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
[0005] :: mov s2, &flag[0]
[0007] :: mov(1) s4, s2
[0008] :: [ARRAY SLOT]
[0009] :: mov arr[15], &1585408084625667200
[0010] :: mov arr[16], &195
[0011] :: mov s3, &arr[15]
[0012] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0013] :: add arr[15], s3, 0
[0014] :: mov s2, &r101002.r_address
[0016] :: mov(24) arr[15], s2
[0017] :: [ARRAY SLOT]
[0018] :: mov arr[42], &141015791240320
[0019] :: mov arr[43], &195
[0020] :: mov s3, &arr[42]
[0021] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0022] :: add arr[42], s3, 0
[0023] :: mov arr[42], s2
[0024] :: mov s2, &s4
[0026] :: mov(1) arr[0], s2
[0027] :: mov s2, &flag[1]
[0028] :: mov s4, s2
[0029] :: [ARRAY SLOT]
[0030] :: mov arr[78], &1657465678663595136
[0031] :: mov arr[79], &195
[0032] :: mov s3, &arr[78]
[0033] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0034] :: add arr[78], s3, 0
[0035] :: mov s2, &r101002.r_address
[0037] :: mov(24) arr[78], s2
[0038] :: [ARRAY SLOT]
[0039] :: mov arr[105], &72198609829168256
[0040] :: mov arr[106], &195
[0041] :: mov s3, &arr[105]
[0042] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0043] :: add arr[105], s3, 0
[0044] :: mov arr[105], s2
[0045] :: mov s2, &s4
[0047] :: mov(1) arr[0], s2
[0048] :: mov s2, &flag[2]
[0049] :: mov s4, s2
[0050] :: [ARRAY SLOT]
[0051] :: mov arr[141], &1153062520398099584
[0052] :: mov arr[142], &195
[0053] :: mov s3, &arr[141]
[0054] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0055] :: add arr[141], s3, 0
[0056] :: mov s2, &r101002.r_address
[0058] :: mov(24) arr[141], s2
[0059] :: [ARRAY SLOT]
[0060] :: mov arr[168], &144256203867096192
[0061] :: mov arr[169], &195
[0062] :: mov s3, &arr[168]
[0063] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0064] :: add arr[168], s3, 0
[0065] :: mov arr[168], s2
[0066] :: mov s2, &s4
[0068] :: mov(1) arr[0], s2
[0069] :: mov s2, &flag[3]
[0070] :: mov s4, s2
[0071] :: [ARRAY SLOT]
[0072] :: mov arr[204], &1297177708473955456
[0073] :: mov arr[205], &195
[0074] :: mov s3, &arr[204]
[0075] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0076] :: add arr[204], s3, 0
[0077] :: mov s2, &r101002.r_address
[0079] :: mov(24) arr[204], s2
[0080] :: [ARRAY SLOT]
[0081] :: mov arr[231], &216313797905024128
[0082] :: mov arr[232], &195
[0083] :: mov s3, &arr[231]
[0084] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0085] :: add arr[231], s3, 0
[0086] :: mov arr[231], s2
[0087] :: mov s2, &s4
[0089] :: mov(1) arr[0], s2
[0090] :: mov s2, &flag[4]
[0091] :: mov s4, s2
[0092] :: exec r92.r_address <- 803425cc40800010c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x10
--------------------
[0101] :: array [0x4008040cc250480, 0xc3, 0x0]
[0104] :: mov s3, &r101.r_address
[0105] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0106] :: add r101.r_address, s3, 0
[0107] :: mov r101.r_address, s2
[0108] :: mov s2, &s4
[0110] :: mov(1) arr[0], s2
[0111] :: mov s2, &flag[5]
[0112] :: mov s4, s2
[0113] :: exec r113.r_address <- 803425cc40800011c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x11
--------------------
[0122] :: array [0x5008040cc250480, 0xc3, 0x0]
[0125] :: mov s3, &r122.r_address
[0126] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0127] :: add r122.r_address, s3, 0
[0128] :: mov r122.r_address, s2
[0129] :: mov s2, &s4
[0131] :: mov(1) arr[0], s2
[0132] :: mov s2, &flag[6]
[0133] :: mov s4, s2
[0134] :: exec r134.r_address <- 803425cc40800012c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x12
--------------------
[0143] :: array [0x6008040cc250480, 0xc3, 0x0]
[0146] :: mov s3, &r143.r_address
[0147] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0148] :: add r143.r_address, s3, 0
[0149] :: mov r143.r_address, s2
[0150] :: mov s2, &s4
[0152] :: mov(1) arr[0], s2
[0153] :: mov s2, &flag[7]
[0154] :: mov s4, s2
[0155] :: exec r155.r_address <- 803425cc40800013c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x13
--------------------
[0164] :: array [0x7008040cc250480, 0xc3, 0x0]
[0167] :: mov s3, &r164.r_address
[0168] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0169] :: add r164.r_address, s3, 0
[0170] :: mov r164.r_address, s2
[0171] :: mov s2, &s4
[0173] :: mov(1) arr[0], s2
[0174] :: mov s2, &flag[8]
[0175] :: mov s4, s2
[0176] :: exec r176.r_address <- 803425cc40800014c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x14
--------------------
[0185] :: array [0x8008040cc250480, 0xc3, 0x0]
[0188] :: mov s3, &r185.r_address
[0189] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0190] :: add r185.r_address, s3, 0
[0191] :: mov r185.r_address, s2
[0192] :: mov s2, &s4
[0194] :: mov(1) arr[1], s2
[0195] :: mov s2, &flag[9]
[0196] :: mov s4, s2
[0197] :: exec r197.r_address <- 803425cc40800015c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x15
--------------------
[0206] :: array [0x9008040cc250480, 0xc3, 0x0]
[0209] :: mov s3, &r206.r_address
[0210] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0211] :: add r206.r_address, s3, 0
[0212] :: mov r206.r_address, s2
[0213] :: mov s2, &s4
[0215] :: mov(1) arr[1], s2
[0216] :: mov s2, &flag[10]
[0217] :: mov s4, s2
[0218] :: exec r218.r_address <- 803425cc40800016c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x16
--------------------
[0227] :: array [0xa008040cc250480, 0xc3, 0x0]
[0230] :: mov s3, &r227.r_address
[0231] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0232] :: add r227.r_address, s3, 0
[0233] :: mov r227.r_address, s2
[0234] :: mov s2, &s4
[0236] :: mov(1) arr[1], s2
[0237] :: mov s2, &flag[11]
[0238] :: mov s4, s2
[0239] :: exec r239.r_address <- 803425cc40800017c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x17
--------------------
[0248] :: array [0xb008040cc250480, 0xc3, 0x0]
[0251] :: mov s3, &r248.r_address
[0252] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0253] :: add r248.r_address, s3, 0
[0254] :: mov r248.r_address, s2
[0255] :: mov s2, &s4
[0257] :: mov(1) arr[1], s2
[0258] :: mov s2, &flag[12]
[0259] :: mov s4, s2
[0260] :: exec r260.r_address <- 803425cc40800018c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x18
--------------------
[0269] :: array [0xc008040cc250480, 0xc3, 0x0]
[0272] :: mov s3, &r269.r_address
[0273] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0274] :: add r269.r_address, s3, 0
[0275] :: mov r269.r_address, s2
[0276] :: mov s2, &s4
[0278] :: mov(1) arr[1], s2
[0279] :: mov s2, &flag[13]
[0280] :: mov s4, s2
[0281] :: exec r281.r_address <- 803425cc40800019c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x19
--------------------
[0290] :: array [0xd008040cc250480, 0xc3, 0x0]
[0293] :: mov s3, &r290.r_address
[0294] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0295] :: add r290.r_address, s3, 0
[0296] :: mov r290.r_address, s2
[0297] :: mov s2, &s4
[0299] :: mov(1) arr[1], s2
[0300] :: mov s2, &flag[14]
[0301] :: mov s4, s2
[0302] :: exec r302.r_address <- 803425cc40800024c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x24
--------------------
[0311] :: array [0xe008040cc250480, 0xc3, 0x0]
[0314] :: mov s3, &r311.r_address
[0315] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0316] :: add r311.r_address, s3, 0
[0317] :: mov r311.r_address, s2
[0318] :: mov s2, &s4
[0320] :: mov(1) arr[1], s2
[0321] :: mov s2, &flag[15]
[0322] :: mov s4, s2
[0323] :: exec r323.r_address <- 803425cc4080002cc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x2c
--------------------
[0332] :: array [0xf008040cc250480, 0xc3, 0x0]
[0335] :: mov s3, &r332.r_address
[0336] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0337] :: add r332.r_address, s3, 0
[0338] :: mov r332.r_address, s2
[0339] :: mov s2, &s4
[0341] :: mov(1) arr[1], s2
[0342] :: mov s2, &flag[16]
[0343] :: mov s4, s2
[0344] :: exec r344.r_address <- 803425cc40800026c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x26
--------------------
[0353] :: array [0x10008040cc250480, 0xc3, 0x0]
[0356] :: mov s3, &r353.r_address
[0357] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0358] :: add r353.r_address, s3, 0
[0359] :: mov r353.r_address, s2
[0360] :: mov s2, &s4
[0362] :: mov(1) arr[2], s2
[0363] :: mov s2, &flag[17]
[0364] :: mov s4, s2
[0365] :: exec r365.r_address <- 803425cc4080001ec3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x1e
--------------------
[0374] :: array [0x11008040cc250480, 0xc3, 0x0]
[0377] :: mov s3, &r374.r_address
[0378] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0379] :: add r374.r_address, s3, 0
[0380] :: mov r374.r_address, s2
[0381] :: mov s2, &s4
[0383] :: mov(1) arr[2], s2
[0384] :: mov s2, &flag[18]
[0385] :: mov s4, s2
[0386] :: exec r386.r_address <- 803425cc4080001fc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x1f
--------------------
[0395] :: array [0x12008040cc250480, 0xc3, 0x0]
[0398] :: mov s3, &r395.r_address
[0399] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0400] :: add r395.r_address, s3, 0
[0401] :: mov r395.r_address, s2
[0402] :: mov s2, &s4
[0404] :: mov(1) arr[2], s2
[0405] :: mov s2, &flag[19]
[0406] :: mov s4, s2
[0407] :: exec r407.r_address <- 803425cc40800020c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x20
--------------------
[0416] :: array [0x13008040cc250480, 0xc3, 0x0]
[0419] :: mov s3, &r416.r_address
[0420] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0421] :: add r416.r_address, s3, 0
[0422] :: mov r416.r_address, s2
[0423] :: mov s2, &s4
[0425] :: mov(1) arr[2], s2
[0426] :: mov s2, &flag[20]
[0427] :: mov s4, s2
[0428] :: exec r428.r_address <- 803425cc40800020c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x20
--------------------
[0437] :: array [0x14008040cc250480, 0xc3, 0x0]
[0440] :: mov s3, &r437.r_address
[0441] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0442] :: add r437.r_address, s3, 0
[0443] :: mov r437.r_address, s2
[0444] :: mov s2, &s4
[0446] :: mov(1) arr[2], s2
[0447] :: mov s2, &flag[21]
[0448] :: mov s4, s2
[0449] :: exec r449.r_address <- 803425cc40800021c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x21
--------------------
[0458] :: array [0x15008040cc250480, 0xc3, 0x0]
[0461] :: mov s3, &r458.r_address
[0462] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0463] :: add r458.r_address, s3, 0
[0464] :: mov r458.r_address, s2
[0465] :: mov s2, &s4
[0467] :: mov(1) arr[2], s2
[0468] :: mov s2, &flag[22]
[0469] :: mov s4, s2
[0470] :: exec r470.r_address <- 803425cc40800023c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x23
--------------------
[0479] :: array [0x16008040cc250480, 0xc3, 0x0]
[0482] :: mov s3, &r479.r_address
[0483] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0484] :: add r479.r_address, s3, 0
[0485] :: mov r479.r_address, s2
[0486] :: mov s2, &s4
[0488] :: mov(1) arr[2], s2
[0489] :: mov s2, &flag[23]
[0490] :: mov s4, s2
[0491] :: exec r491.r_address <- 803425cc40800027c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x27
--------------------
[0500] :: array [0x17008040cc250480, 0xc3, 0x0]
[0503] :: mov s3, &r500.r_address
[0504] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0505] :: add r500.r_address, s3, 0
[0506] :: mov r500.r_address, s2
[0507] :: mov s2, &s4
[0509] :: mov(1) arr[2], s2
[0510] :: mov s2, &flag[24]
[0511] :: mov s4, s2
[0512] :: exec r512.r_address <- 803425cc40800024c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x24
--------------------
[0521] :: array [0x18008040cc250480, 0xc3, 0x0]
[0524] :: mov s3, &r521.r_address
[0525] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0526] :: add r521.r_address, s3, 0
[0527] :: mov r521.r_address, s2
[0528] :: mov s2, &s4
[0530] :: mov(1) arr[3], s2
[0531] :: mov s2, &flag[25]
[0532] :: mov s4, s2
[0533] :: exec r533.r_address <- 803425cc40800025c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x25
--------------------
[0542] :: array [0x19008040cc250480, 0xc3, 0x0]
[0545] :: mov s3, &r542.r_address
[0546] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0547] :: add r542.r_address, s3, 0
[0548] :: mov r542.r_address, s2
[0549] :: mov s2, &s4
[0551] :: mov(1) arr[3], s2
[0552] :: mov s2, &flag[26]
[0553] :: mov s4, s2
[0554] :: exec r554.r_address <- 803425cc40800026c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x26
--------------------
[0563] :: array [0x1a008040cc250480, 0xc3, 0x0]
[0566] :: mov s3, &r563.r_address
[0567] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0568] :: add r563.r_address, s3, 0
[0569] :: mov r563.r_address, s2
[0570] :: mov s2, &s4
[0572] :: mov(1) arr[3], s2
[0573] :: mov s2, &flag[27]
[0574] :: mov s4, s2
[0575] :: exec r575.r_address <- 803425cc40800027c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [s4], 0x27
--------------------
[0584] :: array [0x1b008040cc250480, 0xc3, 0x0]
[0587] :: mov s3, &r584.r_address
[0588] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0589] :: add r584.r_address, s3, 0
[0590] :: mov r584.r_address, s2
[0591] :: mov s2, &s4
[0593] :: mov(1) arr[3], s2
[0594] :: mov s4, &0
[0595] :: mov fail(), &0
[0596] :: mov s5, &0
[0597] :: mov s2, &arr[0]
[0599] :: mov s6, s2
[0600] :: exec r600.r_address <- 803425fc40800070c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x70
--------------------
[0609] :: mov s2, &s6
[0611] :: add s5, s5, s2
[0614] :: mov s6, &0
[0615] :: mov s2, &arr[0]
[0616] :: mov s6, s2
[0617] :: exec r617.r_address <- 803425fc4080007cc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x7c
--------------------
[0626] :: mov s2, &s6
[0628] :: add s5, s5, s2
[0631] :: mov s6, &0
[0632] :: mov s2, &arr[0]
[0633] :: mov s6, s2
[0634] :: exec r634.r_address <- 803425fc40800073c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x73
--------------------
[0643] :: mov s2, &s6
[0645] :: add s5, s5, s2
[0648] :: mov s6, &0
[0649] :: mov s2, &arr[0]
[0650] :: mov s6, s2
[0651] :: exec r651.r_address <- 803425fc40800078c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x78
--------------------
[0660] :: mov s2, &s6
[0662] :: add s5, s5, s2
[0665] :: mov s6, &0
[0666] :: mov s2, &arr[0]
[0667] :: mov s6, s2
[0668] :: exec r668.r_address <- 803425fc4080006fc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x6f
--------------------
[0677] :: mov s2, &s6
[0679] :: add s5, s5, s2
[0682] :: mov s6, &0
[0683] :: mov s2, &arr[0]
[0684] :: mov s6, s2
[0685] :: exec r685.r_address <- 803425fc40800027c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x27
--------------------
[0694] :: mov s2, &s6
[0696] :: add s5, s5, s2
[0699] :: mov s6, &0
[0700] :: mov s2, &arr[0]
[0701] :: mov s6, s2
[0702] :: exec r702.r_address <- 803425fc4080002ac3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x2a
--------------------
[0711] :: mov s2, &s6
[0713] :: add s5, s5, s2
[0716] :: mov s6, &0
[0717] :: mov s2, &arr[0]
[0718] :: mov s6, s2
[0719] :: exec r719.r_address <- 803425fc4080002cc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x2c
--------------------
[0728] :: mov s2, &s6
[0730] :: add s5, s5, s2
[0733] :: mov s6, &0
[0734] :: mov s2, &arr[1]
[0735] :: mov s6, s2
[0736] :: exec r736.r_address <- 803425fc4080007fc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x7f
--------------------
[0745] :: mov s2, &s6
[0747] :: add s5, s5, s2
[0750] :: mov s6, &0
[0751] :: mov s2, &arr[1]
[0752] :: mov s6, s2
[0753] :: exec r753.r_address <- 803425fc40800035c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x35
--------------------
[0762] :: mov s2, &s6
[0764] :: add s5, s5, s2
[0767] :: mov s6, &0
[0768] :: mov s2, &arr[1]
[0769] :: mov s6, s2
[0770] :: exec r770.r_address <- 803425fc4080002dc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x2d
--------------------
[0779] :: mov s2, &s6
[0781] :: add s5, s5, s2
[0784] :: mov s6, &0
[0785] :: mov s2, &arr[1]
[0786] :: mov s6, s2
[0787] :: exec r787.r_address <- 803425fc40800032c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x32
--------------------
[0796] :: mov s2, &s6
[0798] :: add s5, s5, s2
[0801] :: mov s6, &0
[0802] :: mov s2, &arr[1]
[0803] :: mov s6, s2
[0804] :: exec r804.r_address <- 803425fc40800037c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x37
--------------------
[0813] :: mov s2, &s6
[0815] :: add s5, s5, s2
[0818] :: mov s6, &0
[0819] :: mov s2, &arr[1]
[0820] :: mov s6, s2
[0821] :: exec r821.r_address <- 803425fc4080003bc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x3b
--------------------
[0830] :: mov s2, &s6
[0832] :: add s5, s5, s2
[0835] :: mov s6, &0
[0836] :: mov s2, &arr[1]
[0837] :: mov s6, s2
[0838] :: exec r838.r_address <- 803425fc40800022c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x22
--------------------
[0847] :: mov s2, &s6
[0849] :: add s5, s5, s2
[0852] :: mov s6, &0
[0853] :: mov s2, &arr[1]
[0854] :: mov s6, s2
[0855] :: exec r855.r_address <- 803425fc40800059c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x59
--------------------
[0864] :: mov s2, &s6
[0866] :: add s5, s5, s2
[0869] :: mov s6, &0
[0870] :: mov s2, &arr[2]
[0871] :: mov s6, s2
[0872] :: exec r872.r_address <- 803425fc40800053c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x53
--------------------
[0881] :: mov s2, &s6
[0883] :: add s5, s5, s2
[0886] :: mov s6, &0
[0887] :: mov s2, &arr[2]
[0888] :: mov s6, s2
[0889] :: exec r889.r_address <- 803425fc4080008ec3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x8e
--------------------
[0898] :: mov s2, &s6
[0900] :: add s5, s5, s2
[0903] :: mov s6, &0
[0904] :: mov s2, &arr[2]
[0905] :: mov s6, s2
[0906] :: exec r906.r_address <- 803425fc4080003dc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x3d
--------------------
[0915] :: mov s2, &s6
[0917] :: add s5, s5, s2
[0920] :: mov s6, &0
[0921] :: mov s2, &arr[2]
[0922] :: mov s6, s2
[0923] :: exec r923.r_address <- 803425fc4080002ac3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x2a
--------------------
[0932] :: mov s2, &s6
[0934] :: add s5, s5, s2
[0937] :: mov s6, &0
[0938] :: mov s2, &arr[2]
[0939] :: mov s6, s2
[0940] :: exec r940.r_address <- 803425fc40800059c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x59
--------------------
[0949] :: mov s2, &s6
[0951] :: add s5, s5, s2
[0954] :: mov s6, &0
[0955] :: mov s2, &arr[2]
[0956] :: mov s6, s2
[0957] :: exec r957.r_address <- 803425fc40800027c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x27
--------------------
[0966] :: mov s2, &s6
[0968] :: add s5, s5, s2
[0971] :: mov s6, &0
[0972] :: mov s2, &arr[2]
[0973] :: mov s6, s2
[0974] :: exec r974.r_address <- 803425fc4080002dc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x2d
--------------------
[0983] :: mov s2, &s6
[0985] :: add s5, s5, s2
[0988] :: mov s6, &0
[0989] :: mov s2, &arr[2]
[0990] :: mov s6, s2
[0991] :: exec r991.r_address <- 803425fc40800029c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x29
--------------------
[1000] :: mov s2, &s6
[1002] :: add s5, s5, s2
[1005] :: mov s6, &0
[1006] :: mov s2, &arr[3]
[1007] :: mov s6, s2
[1008] :: exec r1008.r_address <- 803425fc40800034c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x34
--------------------
[1017] :: mov s2, &s6
[1019] :: add s5, s5, s2
[1022] :: mov s6, &0
[1023] :: mov s2, &arr[3]
[1024] :: mov s6, s2
[1025] :: exec r1025.r_address <- 803425fc4080002dc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x2d
--------------------
[1034] :: mov s2, &s6
[1036] :: add s5, s5, s2
[1039] :: mov s6, &0
[1040] :: mov s2, &arr[3]
[1041] :: mov s6, s2
[1042] :: exec r1042.r_address <- 803425fc40800061c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x61
--------------------
[1051] :: mov s2, &s6
[1053] :: add s5, s5, s2
[1056] :: mov s6, &0
[1057] :: mov s2, &arr[3]
[1058] :: mov s6, s2
[1059] :: exec r1059.r_address <- 803425fc40800032c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x8040fc], 0x32
--------------------
[1068] :: mov s2, &s6
[1070] :: add s5, s5, s2
[1073] :: mov s6, &0
[1074] :: mov s2, &flag[28]
[1075] :: mov s6, s2
[1076] :: mov s2, &flag[29]
[1077] :: mov s7, s2
[1078] :: mov s8, &0
[1079] :: mov s2, &s8
[1080] :: add s8, s8, s2
[1083] :: mov s2, &s6
[1084] :: add s8, s8, s2
[1087] :: mov s9, &0
[1088] :: mov s2, &s9
[1089] :: add s9, s9, s2
[1092] :: mov s2, &s7
[1093] :: add s9, s9, s2
[1096] :: mov s2, &s9
[1097] :: add s10, s8, s2
[1100] :: exec r1100.r_address <- 8034255c4180006cc3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x80415c], 0x6c
--------------------
[1109] :: mov s2, &s10
[1111] :: add s5, s5, s2
[1114] :: mov s6, &0
[1115] :: mov s7, &0
[1116] :: mov s8, &0
[1117] :: mov s9, &0
[1118] :: mov s10, &0
[1119] :: mov s2, &flag[28]
[1120] :: mov s6, s2
[1121] :: mov s2, &flag[29]
[1122] :: mov s7, s2
[1123] :: mov s8, &0
[1124] :: mov s2, &s8
[1125] :: add s8, s8, s2
[1128] :: mov s2, &s6
[1129] :: add s8, s8, s2
[1132] :: mov s2, &s8
[1133] :: add s8, s8, s2
[1136] :: mov s9, &0
[1137] :: mov s2, &s9
[1138] :: add s9, s9, s2
[1141] :: mov s2, &s7
[1142] :: add s9, s9, s2
[1145] :: mov s2, &s9
[1146] :: add s10, s8, s2
[1149] :: exec r1149.r_address <- 8034255c418000a1c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x80415c], 0xa1
--------------------
[1158] :: mov s2, &s10
[1160] :: add s5, s5, s2
[1163] :: mov s6, &0
[1164] :: mov s7, &0
[1165] :: mov s8, &0
[1166] :: mov s9, &0
[1167] :: mov s10, &0
[1168] :: mov s2, &flag[30]
[1169] :: mov s6, s2
[1170] :: mov s2, &flag[31]
[1171] :: mov s7, s2
[1172] :: mov s8, &0
[1173] :: mov s2, &s8
[1174] :: add s8, s8, s2
[1177] :: mov s2, &s6
[1178] :: add s8, s8, s2
[1181] :: mov s9, &0
[1182] :: mov s2, &s9
[1183] :: add s9, s9, s2
[1186] :: mov s2, &s7
[1187] :: add s9, s9, s2
[1190] :: mov s2, &s9
[1191] :: add s10, s8, s2
[1194] :: exec r1194.r_address <- 8034255c418000b1c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x80415c], 0xb1
--------------------
[1203] :: mov s2, &s10
[1205] :: add s5, s5, s2
[1208] :: mov s6, &0
[1209] :: mov s7, &0
[1210] :: mov s8, &0
[1211] :: mov s9, &0
[1212] :: mov s10, &0
[1213] :: mov s2, &flag[30]
[1214] :: mov s6, s2
[1215] :: mov s2, &flag[31]
[1216] :: mov s7, s2
[1217] :: mov s8, &0
[1218] :: mov s2, &s8
[1219] :: add s8, s8, s2
[1222] :: mov s2, &s6
[1223] :: add s8, s8, s2
[1226] :: mov s2, &s8
[1227] :: add s8, s8, s2
[1230] :: mov s9, &0
[1231] :: mov s2, &s9
[1232] :: add s9, s9, s2
[1235] :: mov s2, &s7
[1236] :: add s9, s9, s2
[1239] :: mov s2, &s9
[1240] :: add s10, s8, s2
[1243] :: exec r1243.r_address <- 8034255c418000e5c3000000000000000000000000000000
--------------------
0x0: xor byte ptr [0x80415c], 0xe5
--------------------
[1252] :: mov s2, &s10
[1254] :: add s5, s5, s2
[1257] :: mov s6, &0
[1258] :: mov s7, &0
[1259] :: mov s8, &0
[1260] :: mov s9, &0
[1261] :: mov s10, &0
[1262] :: mov s2, &s5
[1264] :: mov(1) fail(),

我们选择一个进行分析

1
2
3
4
5
6
7
8
9
10
11
12
    0x0:	xor	byte ptr [s4], 0x10
--------------------
[0101] :: array [0x4008040cc250480, 0xc3, 0x0]
[0104] :: mov s3, &r101.r_address
[0105] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0106] :: add r101.r_address, s3, 0
[0107] :: mov r101.r_address, s2
[0108] :: mov s2, &s4
[0110] :: mov(1) arr[0], s2
[0111] :: mov s2, &flag[5]
[0112] :: mov s4, s2
[0113] :: exec r113.r_address <- 803425cc40800011c3000000000000000000000000000000

array里的机器码转变顺序放到ida里就是add 0x4,后面的exec其实就是个异或,那么我们能够看出这个题的逻辑是flag先异或在加上自己在数组的位置就等于后面的encflag,根据提示还得爆破后4位才行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import hashlib
xor=[0x16,0x17,0x10,0x12,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x24,0x2c,0x26,0x1e,0x1f,0x20,0x20,0x21,0x23,0x27,0x24,0x25,0x26,0x27]
encflag=[0x70,0x7c,0x73,0x78,0x6f,0x27,0x2a,0x2c,0x7f,0x35,0x2d,0x32,0x37,0x3b,0x22,0x59,0x53,0x8e,0x3d,0x2a,0x59,0x27,0x2d,0x29,0x34,0x2d,0x61,0x32]
a=""
for i in range(len(encflag)):
a+=chr((encflag[i]-i)^xor[i])
l = "1234567890abcdef"
for b in l:
for c in l:
for d in l:
flag = a+b+c+d+"}"
sha = hashlib.sha256(flag.encode("utf-8")).hexdigest()
if sha[0:16] == "f860464d767610bb":
print(flag)
break

gamemaster

是个经典21点游戏

发现dll文件是c#写的,放入dnspy,发现似乎是对文件异或和进行了aes加密,那么源文件已经给了,直接模拟生成一下

image-20220802171638649

发现里面有个MZ签名,dump出来还是一个c#写的

EasyRe

这个题每一行都要分析,能学到很多东西。

先用finger跑一下会发现清晰很多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
__int64 __fastcall sub_4021BB(__int64 a1, __int64 a2)
{
int v2; // er8
int v3; // er9
unsigned int v5; // [rsp+1Ch] [rbp-4h]

sub_402150();//将re3的shellcode写到文件中
v5 = fork();//创建子进程,返回子进程id
if ( v5 )
{
sub_401F2F(v5);//主进程进入函数
remove((__int64)"re3");
}
else
{
sys_ptrace(PTRACE_TRACEME, 0LL, 0LL, 0LL, v12, v13, a2);//ptrace函数
sub_44B680((unsigned int)"re3", (unsigned int)"re3", *(_QWORD *)(a2 + 8), 0, v2, v3, a2);
}
return 0LL;
}

ptrace函数最重要的是第一个参数request,它决定了系统调用

image-20220830094057553

我们主要看主进程进入的函数

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
__int64 __fastcall sub_401F2F(unsigned int a1)
{
__int64 v1; // r8
__int64 v2; // r9
unsigned int v3; // ecx
__int64 v4; // rdx
__int64 result; // rax
__int64 v6; // r8
__int64 v7; // r9
__int64 v8; // r8
__int64 v9; // r9
__int64 v10; // r8
__int64 v11; // r9
__int64 v12; // r8
__int64 v13; // r9
__int64 v14; // r8
__int64 v15; // r9
char v16; // [rsp+0h] [rbp-130h]
char v17; // [rsp+0h] [rbp-130h]
char v18; // [rsp+0h] [rbp-130h]
char v19; // [rsp+0h] [rbp-130h]
unsigned int v20; // [rsp+10h] [rbp-120h]
__int64 v21; // [rsp+18h] [rbp-118h]
int v22; // [rsp+2Ch] [rbp-104h] BYREF
char v23[128]; // [rsp+30h] [rbp-100h] BYREF
__int64 v24; // [rsp+B0h] [rbp-80h]
__int64 v25; // [rsp+108h] [rbp-28h]
__int64 v26; // [rsp+110h] [rbp-20h]
__int64 v27; // [rsp+118h] [rbp-18h]
int i; // [rsp+124h] [rbp-Ch]
__int64 v29; // [rsp+128h] [rbp-8h]

sys_wait(a1, 0LL, 0);//等待子进程信号
sys_ptrace(PTRACE_CONT, a1, 0LL, 0LL, v1, v2, v16);//重新运行处于stopped状态程序
v27 = sub_401A30(a1);
v3 = sub_4017E5();//如下表,将下表数据存到result
result = v4;
v20 = v3;
v21 = v4;
for ( i = 0; i <= 2; ++i )
{
v22 = 0;
sys_wait(a1, &v22, 0); //等待子进程信号
result = v22 & 0x7F;
if ( (v22 & 0x7F) == 0 )
break;
sys_ptrace(PTRACE_GETREGS, a1, 0LL, v23, v6, v7, v17);//复制通用寄存器
v26 = v24 - 1;
v25 = sys_ptrace(PTRACE_PEEKTEXT, a1, v24 - 1, 0LL, v8, v9, v18);//子进程给父进程数据
if ( v25 == 0xCAFEB055BFCCLL )
{
v29 = v26;
sub_401BB1(a1, v26, v27, v20, v21);
v24 = v26 + 10;
sys_ptrace(13LL, a1, 0LL, v23, v12, v13, v19);
}
else if ( v25 == 0xCAFE1055BFCCLL )
{
sub_401D78(a1, v29, v26, v27, v20, v21);
v24 = v26 + 10;
sys_ptrace(PTRACE_SETREGS, a1, 0LL, v23, v14, v15, v19);
}
result = sys_ptrace(PTRACE_CONT, a1, 0LL, 0LL, v10, v11, v19);
}
return result;
}

image-20220830102915693

当子进程给父进程数据时,有两个选择,我们需要知道进入了哪个地方。

接下来看re3这个数据

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
__int64 __fastcall main(int a1, char **a2, char **a3)
{
struct __jmp_buf_tag env[1]; // [rsp+10h] [rbp-850h] BYREF
struct __jmp_buf_tag v5[1]; // [rsp+E0h] [rbp-780h] BYREF
struct __jmp_buf_tag v6[1]; // [rsp+1B0h] [rbp-6B0h] BYREF
struct __jmp_buf_tag v7[1]; // [rsp+280h] [rbp-5E0h] BYREF
char v8[640]; // [rsp+350h] [rbp-510h] BYREF
char v9[636]; // [rsp+5D0h] [rbp-290h] BYREF
int v10; // [rsp+84Ch] [rbp-14h]
int v11; // [rsp+850h] [rbp-10h]
int v12; // [rsp+854h] [rbp-Ch]
int v13; // [rsp+858h] [rbp-8h]
int v14; // [rsp+85Ch] [rbp-4h]
__int64 savedregs; // [rsp+860h] [rbp+0h] BYREF

v14 = 1;
if ( a1 != 2 )
return 0LL;
(sub_2490)(a2[1], a2, a3);//主要加密我们现在不关心
(loc_21F9)(&unk_55C0, v9, v8);//这个地方要注意
v13 = _setjmp(env);
if ( v13 <= 24 )
{
v11 = _setjmp(v5);
if ( v11 < byte_50A0[25 * v13] )
{
if ( byte_50A0[25 * v13 + 1 + v11] != *(&savedregs + 25 * v13 + v11 - 655) )
v14 = 0;
longjmp(v5, v11 + 1);
}
longjmp(env, v13 + 1);
}
v12 = _setjmp(v6);
if ( v12 <= 24 )
{
v10 = _setjmp(v7);
if ( v10 < byte_5320[25 * v12] )
{
if ( byte_5320[25 * v12 + 1 + v10] != *(&savedregs + 25 * v12 + v10 - 1295) )
v14 = 0;
longjmp(v7, v10 + 1);
}
longjmp(v6, v12 + 1);
}
if ( v14 == 1 )
puts("GOOD JOB");
return 0LL;
}
1
(loc_21F9)(&unk_55C0, v9, v8);

这个地方的数据非常奇怪,无法反编译,我们需要仔细看一下

image-20220830105602247

发现int 3,并且有一个CAFEB055BF这样一个数据,这个数据是在主进程里进行判断的数据,那么我们可以推测这个题的主要逻辑就是:主进程先等待子进程运行,子进程抛出int 3等待主进程调试,主进程判断异常类型,进行对上面的smc处理。

获取smc加密后文件的方法有两种:分别是静态分析和动态调试

静态分析:

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
__int64 __fastcall sub_401BB1(unsigned int a1, __int64 a2, int a3, char a4, __int64 a5)
{
__int64 v5; // rcx
__int64 v6; // r8
__int64 v7; // r9
int v8; // er8
int v9; // er9
__int64 v10; // rax
int v11; // er8
int v12; // er9
__int64 v13; // r8
__int64 v14; // r9
__int64 result; // rax
char v16; // [rsp+0h] [rbp-C0h]
unsigned int v17; // [rsp+0h] [rbp-C0h]
char v18; // [rsp+0h] [rbp-C0h]
unsigned __int64 v21; // [rsp+20h] [rbp-A0h]
char v22[32]; // [rsp+30h] [rbp-90h] BYREF
char v23[32]; // [rsp+50h] [rbp-70h] BYREF
char v24[24]; // [rsp+70h] [rbp-50h] BYREF
__int64 v25; // [rsp+88h] [rbp-38h]
__int64 v26; // [rsp+90h] [rbp-30h]
int v27; // [rsp+9Ch] [rbp-24h]
__int64 v28; // [rsp+A0h] [rbp-20h]
int v29; // [rsp+ACh] [rbp-14h]
__int64 v30; // [rsp+B0h] [rbp-10h]
int j; // [rsp+B8h] [rbp-8h]
unsigned int i; // [rsp+BCh] [rbp-4h]

v16 = a4;
v30 = sub_401AC2(a1, a2);
v29 = (v30 - a2 - 10) >> 4;
v21 = a2 + 10;
for ( i = 0; ; ++i )
{
result = i;
if ( i >= v29 )
break;
v28 = sys_ptrace(PTRACE_PEEKTEXT, a1, v21, v5, v6, v7, v16);
v27 = sub_40190E((v21 - a3), v17, a5);
sprintf(v23, &unk_490008, v27, &unk_490008, v8, v9, v17);
v10 = j_strnlen(v23);
md5(v23, v10, v24);
for ( j = 15; j > 7; --j )
sprintf(&v22[2 * (15 - j)], "%02x", v24[j], &v22[2 * (15 - j)], v11, v12, v18);
v26 = sub_40B660(v22, 0LL, 16LL);
v25 = v26 ^ v28;
sys_ptrace(PTRACE_POKETEXT, a1, v21, v26 ^ v28, v13, v14, v18);
v21 += 16LL;
}
return result;
}

我们直接看主进程进入的smc函数,最重要的是一个md5一个异或2,经过动态调试

,可以知道v28是在子程序中取int 3后面的qword,v26是将原始值进行md5后再将从第八个字节倒序。如何获取这个值呢,我们需要利用条件断点

image-20220830115323802

拿到值后我们直接去子进程用idapython恢复一下:

1
2
3
4
5
6
7
8
9
10
xorKey = {8723: 2533025110152939745, 8739: 5590097037203163468, 8755: 17414346542877855401, 8771: 17520503086133755340, 8787: 12492599841064285544, 8803: 12384833368350302160, 8819: 11956541642520230699, 8835: 12628929057681570616, 8851: 910654967627959011, 8867: 5684234031469876551, 8883: 6000358478182005051, 8899: 3341586462889168127, 8915: 11094889238442167020, 8931: 17237527861538956365, 8947: 17178915143649401084, 8963: 11176844209899222046, 8979: 18079493192679046363, 8995: 7090159446630928781, 9011: 863094436381699168, 9027: 6906972144372600884, 9043: 16780793948225765908, 9059: 7086655467811962655, 9075: 13977154540038163446, 9091: 7066662532691991888, 9107: 15157921356638311270, 9123: 12585839823593393444, 9139: 1360651393631625694, 9155: 2139328426318955142, 9171: 2478274715212481947, 9187: 12876028885252459748, 9203: 18132176846268847269, 9219: 17242441603067001509, 9235: 8492111998925944081, 9251: 14679986489201789069, 9267: 13188777131396593592, 9283: 5298970373130621883, 9299: 525902164359904478, 9315: 2117701741234018776, 9331: 9158760851580517972}

addr = 0x2213

while True:
data = get_qword(addr)
key = xorKey[addr]
dec = data ^ key
idc.patch_qword(addr, dec)
addr += 16

动态调试:

也就是经常说的patch死循环,但之前一直没操作过,这次学会了。

patch死循环目的是什么呢?我们知道如果不patch我们是没法在主进程中查看子进程的,通过patch死循环可以直接调试子进程。

为什么for循环3次呢?第一次是int3处理smc解密,第二次是int3处理smc加密,就是将解密完的数据再加密回去,第三次是等待子进程结束。

如何操作?先找到子进程末尾,在末尾写个死循环就是jmp到本地址,第二步为了不使smc又把解密完的数据加密回去,异或改为0,第三步patch 401F2F函数的 for 循环为2

patch前

image-20220830155226276

patch后

image-20220830155301280

异或改为0:

image-20220830155531523

for循环改为1:

image-20220830155554253

修改完后运行发现仍然再跑

image-20220830155922080

image-20220830160100683

成功!

用下面脚本找到smc那个函数:

1
2
3
4
5
a = 0x56534AF3F00C
while(a < 0x56534af3f48d):
if(get_wide_byte(a) == 0x55 and get_wide_byte(a+1) == 0x48 and get_wide_byte(a+4) == 0x48):
print(hex(a),end = ", ")
a+=1

image-20220830160553793

这样就可以把这个dump出来了

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
// positive sp value has been detected, the output may be wrong!
void __fastcall sub_21F9(__int64 input, __int64 data1, __int64 data2)
{
int offsett; // [rsp+20h] [rbp-28h]
int statee; // [rsp+24h] [rbp-24h]
char count2; // [rsp+28h] [rbp-20h]
int jj; // [rsp+2Ch] [rbp-1Ch]
int j; // [rsp+30h] [rbp-18h]
int offset; // [rsp+34h] [rbp-14h]
int state; // [rsp+38h] [rbp-10h]
char lineCount; // [rsp+3Ch] [rbp-Ch]
int ii; // [rsp+40h] [rbp-8h]
int i; // [rsp+44h] [rbp-4h]

for ( i = 0; i <= 24; ++i )
{
ii = 0;
lineCount = 0;
state = 0;
offset = 1;
while ( ii <= 24 )
{
if ( *(25 * i + ii + input) )
{
++lineCount;
state = 1;
}
else
{
if ( state )
{
*(data1 + 25LL * i + offset) = lineCount;
lineCount = 0;
++offset;
}
state = 0;
}
if ( ++ii == 25 && state )
{
*(data1 + 25LL * i + offset) = lineCount;
lineCount = 0;
++offset;
}
}
*(25LL * i + data1) = offset - 1;
}


for ( j = 0; j <= 24; ++j )
{
jj = 0;
count2 = 0;
statee = 0;
offsett = 1;
while ( jj <= 24 )
{
if ( *(25 * jj + j + input) )
{
++count2;
statee = 1;
}
else
{
if ( statee )
{
*(data2 + 25LL * j + offsett) = count2;
count2 = 0;
++offsett;
}
statee = 0;
}
if ( ++jj == 25 )
{
if ( statee )
{
*(data2 + 25LL * j + offsett) = count2;
count2 = 0;
++offsett;
}
}
}
*(25LL * j + data2) = offsett - 1;
}
}

其实前面的操作就很难了,后面这个加密更难,其实是个数织游戏

image-20220830161743593

这个地方取出来的数据其实是不对的,因为在程序运行的时候init段进行了初始化,真正的在

image-20220830161940268

找到在线网站解密就行https://handsomeone.github.io/Nonogram/,注意每行第一个数是偏移,不能出现在解密里

image-20220830162146771