[Attachment](https://plaidctf.com/files/prospectin.cdc5496a4fa3697a4e15149f7493ebfb7e576f674e9ebff8990fc2fa0129375b.tgz)
Script for **Prospecting** challege:
```
import random
import string
import copy
FLAG_LEN = 64
FLAG_PREFIX = "PCTF{"
FLAG_SUFFIX = "}"
CHARSET = string.printable.strip()
POP_SIZE = 400
GENERATIONS = 10000
MUTATION_RATE = 0.03
ELITE_COUNT = 100
def prospect(buf, fn):
fn(buf[0x1b] == 0x32)
fn(0xaa == (buf[0x1f] ^ buf[0x18]))
fn(0x90 == (buf[0x1f] + buf[0x2e]))
fn(0x81 == (buf[0x3b] + buf[0x24]))
fn(buf[0xd] == 0xbe)
fn(0x64 == buf[0x20])
fn(0x31 == buf[0x1a])
fn(0x39 == buf[0x2a])
fn((buf[0x2d] + buf[0x3f]) == 0x93)
fn(buf[0x32] == 0x31)
fn(0x38 == (buf[1] + buf[0xf]))
fn(0x8e == (buf[0xd] ^ buf[0x23]))
fn(0x71 == (buf[1] ^ buf[0x2e]))
fn(0xb4 == buf[0x2a])
fn(0x36 == buf[0x13])
fn(buf[0x1c] == buf[0x30])
fn(3 == (buf[0xa] ^ buf[0x21]))
fn(buf[0x1e] == 0x76)
fn(0x32 == buf[5])
fn((buf[1] ^ buf[0x30]) == 0x85)
fn(buf[2] == 0x54)
fn(0xe1 == buf[0x17])
fn((buf[9] ^ buf[0x36]) == 0x81)
fn(0x61 == (buf[0x35] + buf[0x1a]))
fn((buf[0x12] ^ buf[0x39]) == 7)
fn((buf[0x12] ^ buf[5]) == 0x56)
fn((buf[0xe] + buf[0x35]) == 0x66)
fn(0x54 == (buf[0x30] ^ buf[0x38]))
fn(0xe5 == buf[0x34])
fn(0x6f == buf[0x24])
fn((buf[0x25] + buf[0x1e]) == 0x66)
fn(buf[0x32] == 0x31)
fn(0x38 == buf[0x17])
fn(0x34 == buf[0x27])
fn(0x97 == (buf[0x38] + buf[0x13]))
fn(0x2d == (buf[0x13] ^ buf[0x32]))
fn(0xa4 == (buf[0x22] + buf[1]))
fn(0xf4 == (buf[0x2f] + buf[0x26]))
fn((buf[0x1b] + buf[0x2f]) == 0x97)
fn(0x96 == (buf[0x2f] + buf[0xa]))
fn(0x72 == buf[2])
fn(buf[0x3b] == 0x36)
fn(0xb1 == buf[0x1c])
fn(8 == (buf[8] ^ buf[0x3a]))
fn(0x3a == (buf[2] ^ buf[0x2e]))
fn(buf[0x3b] == 0x44)
fn(0x12 == buf[0x39])
fn((buf[0x11] ^ buf[0x28]) == 0x5b)
fn(buf[0x29] == 0x2a)
fn(0x33 == buf[0x29])
fn((buf[0x1a] + buf[0x26]) == 0x3f)
fn(0x60 == (buf[0x3d] ^ buf[0]))
fn(0x24 == buf[0x15])
fn(0x2d == (buf[5] + buf[0x2b]))
fn(buf[0x39] == 0x63)
fn(5 == (buf[0x37] ^ buf[0x34]))
fn(0x7b == buf[4])
fn((buf[0x10] + buf[9]) == 0xad)
fn((buf[0x16] + buf[0x2d]) == 0x98)
fn(buf[0x18] == 0x32)
fn(buf[0x30] == 0x35)
fn(0x5b == (buf[0x36] ^ buf[0x13]))
fn(0x99 == (buf[0x36] + buf[0xe]))
fn(0xd2 == buf[0x35])
fn((buf[0] ^ buf[0x30]) == 0x65)
fn((buf[0x2a] + buf[0x31]) == 0x9a)
fn((buf[0x14] + buf[0x1d]) == 0x96)
fn(0xda == (buf[0x28] ^ buf[0x32]))
fn(0x96 == (buf[0x3c] + buf[0x20]))
fn((buf[0x27] + buf[7]) == 0x98)
fn(buf[0x32] == buf[0xa])
fn(0x52 == (buf[0x39] ^ buf[0xa]))
fn(buf[0x38] == 0x61)
fn(buf[0x14] == 0x61)
fn((buf[0x3e] ^ buf[8]) == 1)
fn(0x30 == (buf[0x2c] ^ buf[0x22]))
fn(buf[0x21] == 0x32)
fn((buf[0x2f] ^ buf[0x31]) == 4)
fn(0x53 == (buf[0x1b] ^ buf[0x16]))
fn((buf[0] + buf[0x29]) == 0x83)
fn(0xf1 == buf[0x12])
fn(0x35 == buf[0x1c])
fn(buf[0x10] == 0xd3)
fn(0x99 == (buf[6] + buf[0x2f]))
fn((buf[0x1c] + buf[0x19]) == 0xaf)
fn((buf[0x3f] + buf[0x13]) == 0xb3)
fn(0x35 == buf[0x1d])
fn(buf[0x3d] == 0x30)
fn((buf[0xf] + buf[0x19]) == 0x85)
fn(0x4f == (buf[0x14] ^ buf[0x3d]))
fn((buf[0x1b] ^ buf[0x32]) == 3)
fn((buf[0x3e] + buf[0x33]) == 0x62)
fn((buf[0x14] + buf[0x2c]) == 0xc5)
fn(0xc9 == (buf[0x2b] + buf[0x12]))
fn((buf[9] + buf[0x24]) == 0x68)
fn(buf[9] == buf[0x13])
fn((buf[0x13] ^ buf[0x21]) == 4)
fn((buf[0x37] + buf[0]) == 0x85)
fn(buf[0x16] == 0x61)
fn(0x39 == buf[0x11])
fn(buf[0xa] == 0x31)
fn(0x30 == buf[0x35])
fn((buf[0x31] + buf[0x3d]) == 0xe9)
fn(0x31 == buf[0x32])
fn((buf[0x37] + buf[3]) == 0xbf)
fn(0x99 == (buf[0x2d] + buf[0x19]))
fn(0x32 == buf[0x2e])
fn(0x97 == (buf[0x18] + buf[0x2b]))
fn(buf[0x1a] == 0x31)
fn(0x36 == buf[0xe])
fn((buf[3] + buf[0x3e]) == 0x76)
fn(buf[0x1b] == 0x32)
fn(0x4a == (buf[0x3f] ^ buf[0x2d]))
fn((buf[0x2c] + buf[0xe]) == 0xf0)
fn(buf[9] == 0xd8)
fn((buf[0x3a] + buf[0x3e]) == 0x62)
fn(0x93 == (buf[0x3d] + buf[0x16]))
fn(2 == (buf[0x33] ^ buf[0x35]))
fn(0x32 == buf[0x1b])
fn(7 == (buf[0x32] ^ buf[0x3b]))
fn(0x30 == buf[0x34])
fn(buf[0x21] == 0x79)
fn(buf[0x3d] == 0x33)
fn((buf[0x15] + buf[0x31]) == 0xc5)
fn(0x53 == buf[0x24])
fn(buf[0xf] == 9)
fn(0xb4 == (buf[0] + buf[0x20]))
fn(0x68 == (buf[0xe] + buf[0x33]))
fn((buf[0x2b] ^ buf[0xe]) == 0xfb)
fn(0x4f == buf[0x3a])
fn(0x3e == buf[0xa])
fn(0xec == buf[0x2f])
fn(0x37 == buf[0x2d])
fn(0xff == (buf[0x16] + buf[0x3b]))
fn(0x28 == (buf[0x18] ^ buf[2]))
fn(0xd1 == buf[0x30])
fn((buf[0x37] ^ buf[7]) == 0xe8)
fn(0x65 == buf[0x2f])
fn((buf[5] + buf[0x39]) == 0xfc)
fn((buf[0x18] + buf[5]) == 0x64)
fn(2 == (buf[0x22] ^ buf[0x36]))
fn(0x36 == buf[9])
fn(0x32 == buf[5])
fn(0x31 == buf[0x1a])
fn(0x32 == buf[0x3c])
fn((buf[4] + buf[7]) == 0xdf)
fn(0x34 == buf[0x1f])
fn(0x59 == (buf[0x32] ^ buf[0x34]))
fn(0x39 == buf[0x3a])
fn(0x53 == (buf[0xc] ^ buf[0x2b]))
fn(buf[7] == 0x61)
fn((buf[0x35] ^ buf[7]) == 0x54)
fn(0x6a == (buf[0x3b] + buf[6]))
fn((buf[0x11] + buf[0x1c]) == 0x6e)
fn(0x7b == buf[4])
fn(0x65 == buf[0x23])
fn((buf[0x24] + buf[0x2c]) == 0x96)
fn(0x7d == buf[0x3f])
fn(0x5d == (buf[0x1b] ^ buf[0x29]))
fn(buf[0x28] == 0x62)
fn((buf[0x18] ^ buf[0x15]) == 0x63)
fn(0x52 == (buf[0x15] ^ buf[0x13]))
fn(0x31 == buf[0xa])
fn((buf[0x25] + buf[6]) == 0x67)
fn(buf[6] == 0x7b)
fn(0x93 == buf[0x38])
fn((buf[9] ^ buf[0x1d]) == 3)
fn(buf[0x2f] == 0xc7)
fn(buf[0x1d] == 0x35)
fn(0x7d == buf[0x3f])
fn((buf[0x33] + buf[0x26]) == 0x47)
fn(0x93 == (buf[0x3c] + buf[0x14]))
fn((buf[1] ^ buf[0xf]) == 0x74)
fn(0x16 == (buf[0xb] ^ buf[0x3a]))
fn(0x31 == buf[0x32])
fn(0xcd == (buf[0] + buf[0x3f]))
fn(buf[0x3c] == 0x32)
fn(0x63 == buf[0x36])
fn(0x4b == buf[7])
fn((buf[0x1d] ^ buf[0x28]) == 0x57)
fn(0x39 == buf[0x3a])
fn(0x56 == (buf[0x21] ^ buf[0x2c]))
fn(buf[0x11] == 0x96)
fn(buf[0x13] == 0xab)
fn((buf[0x3b] + buf[0x33]) == 0xaf)
fn(0x7f == buf[0x15])
fn(0xd1 == (buf[0x23] ^ buf[0xb]))
fn(0x62 == buf[0x28])
fn((buf[0x12] ^ buf[0xd]) == 0x5e)
fn(buf[7] == 0x16)
fn((buf[0x36] + buf[6]) == 0x97)
fn(buf[0x32] == 0x31)
fn(buf[0x2d] == 0x37)
fn((buf[0x13] + buf[5]) == 0x68)
fn(buf[4] == 0x1a)
fn(buf[0x3e] == 0x30)
fn((buf[0xc] ^ buf[0x18]) == 4)
fn((buf[0x2e] + buf[0x20]) == 0x96)
fn(buf[0x22] == 0x61)
fn(buf[3] == 0x46)
fn(0x97 == (buf[0xb] + buf[0x2f]))
fn(0x32 == buf[0x2e])
fn(0x60 == buf[0x19])
fn(buf[9] == 0x36)
fn(0x3a == buf[0x1a])
fn((buf[0x37] ^ buf[0x2a]) == 0xc)
fn(0x57 == (buf[0x22] ^ buf[0x13]))
fn(0x61 == buf[0x38])
fn((buf[0x2b] ^ buf[0x1f]) == 0x51)
fn(0x35 == buf[0x37])
fn(0xa9 == buf[9])
fn(0x78 == (buf[0x2e] + buf[3]))
fn(0x1f == buf[0x30])
fn(0x9d == (buf[0x23] + buf[0x17]))
fn(0x6d == buf[0x24])
fn(6 == (buf[0x1e] ^ buf[0x1c]))
fn(0x30 == buf[0x35])
fn(0xf7 == buf[0x14])
fn(buf[0x32] == 0x31)
fn((buf[0x3c] + buf[0x2d]) == 0x69)
fn(5 == (buf[0x29] ^ buf[0xc]))
fn((buf[9] ^ buf[0x2a]) == 0x85)
fn(buf[0x20] == 0x64)
fn(0x30 == buf[0x35])
fn(0x67 == (buf[0x26] + buf[0x37]))
fn(buf[0x20] == buf[0xd])
fn(0x32 == buf[0x24])
fn(buf[0x17] == 0x9b)
fn(0x64 == buf[0xd])
fn(buf[8] == 0x31)
fn(buf[0x24] == 0x32)
fn(0xc3 == buf[0xe])
fn((buf[0x29] + buf[0x15]) == 0x97)
fn(0x6a == (buf[0x2d] + buf[0x25]))
fn(0x32 == buf[0x20])
fn(buf[0x2c] == 0x64)
fn(0x54 == buf[2])
fn(0x54 == (buf[0x23] ^ buf[0x32]))
fn(buf[0x33] == 0x32)
fn(0x35 == buf[0x30])
fn(buf[0x29] == 0x33)
fn(buf[0x1b] == 0x32)
fn(0x97 == (buf[0x31] + buf[0x3b]))
fn(buf[0x24] == 0x32)
fn(buf[0x16] == 0x61)
fn((buf[0x37] + buf[4]) == 0x12)
fn(0x9e == buf[0x2e])
fn(0x55 == (buf[0x16] ^ buf[0x1f]))
fn(0x43 == buf[0x32])
fn(0x38 == buf[0x17])
fn(0xc == buf[0x34])
fn(0x30 == buf[0x34])
fn(buf[0x16] == 0x61)
fn(0x36 == buf[0xe])
fn(0x54 == buf[2])
fn(0x50 == (buf[8] ^ buf[0x16]))
fn((buf[0x23] + buf[0]) == 0xa7)
fn((buf[0x27] + buf[2]) == 0xc7)
fn(7 == (buf[0x29] ^ buf[6]))
fn((buf[0x21] + buf[0xb]) == 0xa5)
fn(0x62 == buf[0x19])
fn(0x31 == buf[0x1a])
fn((buf[0x14] + buf[0x1b]) == 0x23)
fn((buf[6] ^ buf[0x23]) == 0x9c)
fn(4 == (buf[0xe] ^ buf[0xb]))
fn(0x34 == buf[0x27])
fn((buf[0x28] + buf[0x1f]) == 0x96)
fn(buf[0x39] == 0x63)
fn(buf[7] == 0x64)
fn(buf[0xe] == 0x36)
fn(buf[5] == 0x43)
fn((buf[0x17] ^ buf[0x16]) == 0x59)
fn(0x64 == buf[0x15])
fn((buf[0x16] ^ buf[0x2c]) == 5)
fn(0x30 == buf[0x35])
fn(0x34 == buf[0x1f])
fn(0x61 == buf[0x16])
fn(0x7a == (buf[0x2e] + buf[8]))
fn((buf[0x19] ^ buf[3]) == 0x24)
fn(buf[0x2b] == 0x65)
fn(0xf == buf[0x2c])
fn(0x57 == (buf[0x10] ^ buf[0x15]))
fn((buf[9] ^ buf[0x3e]) == 6)
fn(buf[0x1b] == 0x32)
fn((buf[0x12] + buf[0x36]) == 0xd1)
fn(buf[0x20] == 0x64)
fn((buf[0x39] + buf[0x12]) == 0xc7)
fn(1 == (buf[0x2b] ^ buf[0x20]))
fn(buf[0x11] == 0xa4)
fn((buf[8] ^ buf[9]) == 7)
fn(buf[0x28] == 0x62)
fn((buf[0x38] + buf[4]) == 0xa)
fn((buf[0x15] + buf[0x1c]) == 0x99)
fn(buf[0xc] == 0x7c)
fn(0xe1 == (buf[0x3f] + buf[0x12]))
fn(buf[0x1b] == 0x32)
fn(buf[0x17] == 0x38)
fn(0xc8 == (buf[0x2c] + buf[0x12]))
fn((buf[9] + buf[0x13]) == 0x6c)
fn((buf[0x3d] + buf[0xb]) == 0xe7)
fn(0x64 == buf[0x15])
fn((buf[0x39] + buf[0x1f]) == 0x97)
fn(0x57 == (buf[0x1c] ^ buf[0x28]))
fn(0x37 == buf[0x2d])
fn(0xc9 == (buf[0xd] + buf[0x2f]))
fn(buf[0x12] == 0x64)
fn(buf[0xf] == 0x37)
fn((buf[0x3a] ^ buf[0x10]) == 0xa)
fn(0x34 == (buf[0] ^ buf[0x15]))
fn((buf[0x3e] + buf[0x31]) == 0x91)
fn(buf[0x2e] == 0x32)
fn(0xa8 == (buf[0x39] + buf[0]))
fn(0x32 == buf[0x24])
fn(0x31 == buf[0x32])
fn(buf[0x30] == 0x35)
fn(buf[0x2a] == 0x39)
fn((buf[0x3d] + buf[0x23]) == 0x95)
fn((buf[0x1b] + buf[1]) == 0x75)
fn(buf[0x30] == 0x35)
fn((buf[0x23] ^ buf[0x21]) == 0x51)
fn((buf[0x1d] ^ buf[0x39]) == 0x56)
fn(buf[0x17] == 0x4b)
fn((buf[0x1f] + buf[0xd]) == 0xac)
fn(buf[0x27] == 0x4a)
fn(0x34 == buf[0x27])
fn(0x73 == buf[0x21])
fn(buf[7] == 0x64)
fn(0x50 == buf[0])
fn(buf[0x16] == 0x61)
fn((buf[0x3e] + buf[0x37]) == 0x65)
fn(buf[0x34] == 0x30)
fn((buf[7] + buf[0x16]) == 0xcc)
fn((buf[0x1a] ^ buf[0xe]) == 7)
fn(0x54 == buf[2])
fn(buf[0x2e] == 0x32)
fn(0x30 == buf[0x34])
fn(6 == (buf[0x36] ^ buf[0x23]))
fn((buf[0x1f] ^ buf[0x22]) == 0x55)
fn(buf[0x21] == 0x32)
fn((buf[0x28] + buf[0x21]) == 0x94)
fn(buf[7] == 0x64)
fn(buf[0xf] == 0x37)
fn(0x54 == (buf[0xa] ^ buf[0x2b]))
fn(buf[0xf] == 0x37)
fn(0x68 == (buf[0x1d] + buf[0x1e]))
fn(1 == (buf[0x2b] ^ buf[0xd]))
fn((buf[0x3a] + buf[0x18]) == 0xd9)
fn(0x69 == (buf[0x11] + buf[0x3d]))
fn(0xa6 == buf[0x29])
fn((buf[0x36] ^ buf[0x18]) == 0x51)
fn(0x30 == buf[0x3e])
fn((buf[0x39] + buf[0x25]) == 0x96)
fn(0x4b == (buf[0x3d] ^ buf[4]))
fn((buf[0x25] + buf[0x34]) == 0x63)
fn(0x3d == (buf[0x15] ^ buf[0x1a]))
fn(buf[0x32] == 0xe9)
fn(7 == (buf[5] ^ buf[0x1d]))
fn(buf[0x1f] == 0x34)
fn(buf[0x35] == 1)
fn((buf[0xf] + buf[7]) == 0x9b)
fn(0x33 == buf[0x29])
fn(0x97 == (buf[0x23] + buf[0x1b]))
fn(buf[0x2a] == 0x39)
fn(buf[0x1b] == 0x32)
fn(buf[0x2f] == 0x65)
fn((buf[0x2d] ^ buf[0x1e]) == 4)
fn(0x33 == buf[0x1e])
fn(buf[0x16] == 0x61)
fn(0x61 == buf[0x31])
fn(0x98 == (buf[0x1f] + buf[0x15]))
fn(buf[0x18] == 0x32)
fn(buf[0xf] == 0x37)
fn(buf[0x23] == 0xcb)
fn((buf[4] + buf[0x25]) == 0xae)
fn(buf[0x31] == 0x61)
fn((buf[7] ^ buf[0x1f]) == 0x50)
fn((buf[0xf] + buf[0x13]) == 0x6d)
fn((buf[0x1e] ^ buf[0x16]) == 0xc7)
fn(1 == (buf[0x10] ^ buf[0x3c]))
fn(0x36 == buf[0xc])
fn(buf[0x1c] == 1)
fn((buf[0x2c] + buf[0x3a]) == 0x9d)
fn((buf[0x31] ^ buf[0x25]) == 0x52)
fn(buf[6] == 0x34)
fn(0x32 == buf[0x26])
fn(0x30 == buf[0x3e])
fn(0x57 == (buf[0x25] ^ buf[0x15]))
fn(0x94 == (buf[0x28] + buf[5]))
fn(0x93 == (buf[0xb] + buf[0x22]))
fn(0x99 == buf[0x2b])
fn((buf[0x16] + buf[0x1b]) == 0x88)
fn(buf[0x2e] == buf[0x26])
fn((buf[0x30] ^ buf[0x3d]) == 5)
fn(0x56 == buf[0xc])
fn((buf[0x2c] ^ buf[0x1c]) == 0x51)
fn(0x37 == buf[0x2d])
fn(0x67 == (buf[0x25] ^ buf[2]))
fn(0x7b == (buf[0x36] ^ buf[0x10]))
fn((buf[0x2d] ^ buf[0x12]) == 0x91)
fn(0x64 == buf[0x12])
def get_score(buf):
global score
score = 0
def fn_chal(x):
global score
if x:
score += 1
prospect(list(buf.encode()), fn_chal)
return score
def random_flag():
middle_len = FLAG_LEN - len(FLAG_PREFIX) - len(FLAG_SUFFIX)
middle = ''.join(random.choices(CHARSET, k=middle_len))
return FLAG_PREFIX + middle + FLAG_SUFFIX
def mutate(flag):
flag = list(flag)
for i in range(len(flag)):
if random.random() < MUTATION_RATE and i >= len(FLAG_PREFIX) and i < FLAG_LEN - len(FLAG_SUFFIX):
flag[i] = random.choice(CHARSET)
return ''.join(flag)
def crossover(parent1, parent2):
idx = random.randint(len(FLAG_PREFIX), FLAG_LEN - len(FLAG_SUFFIX) - 1)
child = parent1[:idx] + parent2[idx:]
return child
population = [random_flag() for _ in range(POP_SIZE)]
for gen in range(GENERATIONS):
scored = [(flag, get_score(flag)) for flag in population]
scored.sort(key=lambda x: x[1], reverse=True)
best = scored[0]
print(f"Generation {gen} | Score : {best[1]}")
if best[1] >= 281:
print(f"\nFlag : {best[0]}")
break
new_population = [f for f, _ in scored[:ELITE_COUNT]]
while len(new_population) < POP_SIZE:
p1, p2 = random.choices(new_population, k=2)
child = mutate(crossover(p1, p2))
new_population.append(child)
population = new_population
```