Metagaming
Catégorie: Reverse Difficulté: hard Flag: HTB{m4n_1_l0v4_cXX_TeMpl4t35_9fb60c17b0}
Challenge
Analyse
Le programme C++ fourni implémente un système d’instructions. On a donc une liste d’instructions qui sont passées au programme pour être exécutées

Puis une vérification sur l’état des registres final est faite pour savoir si nous avions le bon input

On va pas s’amuser à comprendre ce qui se passe en détail dans le programme mais à voir ce qu’il en ressort en fonction de notre input. Pour ce faire, vu que mon c++ est bancal je vais réimplémenter le code en python à l’aide de ChatGPT pour gagner du temps. On mettra tout dans le fichier chall.py
# La liste d'instructions
INSTRUCTIONS = [(12, 13, 10), (21, 0, 0), (0, 13, 13), (0, 14, 0), (15, 11, 12), (24, 14, 0), (5, 0, 14), (0, 14, 1), (7, 11, 11), (24, 14, 8), (5, 0, 14), (0, 14, 2), (2, 10, 11), (24, 14, 16), (18, 12, 11), (5, 0, 14), (0, 14, 3), (0, 11, 11), (24, 14, 24), (13, 10, 10), (5, 0, 14), (2, 11, 13), (21, 1, 0), (0, 14, 4), (24, 14, 0), (5, 1, 14), (6, 11, 12), (0, 14, 5), (8, 10, 10), (24, 14, 8), (11, 12, 11), (5, 1, 14), (0, 14, 6), (0, 12, 10), (24, 14, 16), (9, 10, 13), (5, 1, 14), (0, 14, 7), (13, 12, 12), (24, 14, 24), (15, 10, 12), (5, 1, 14), (21, 2, 0), (20, 13, 13), (0, 14, 8), (24, 14, 0), (19, 10, 11), (5, 2, 14), (6, 12, 10), (0, 14, 9), (8, 11, 11), (24, 14, 8), (5, 2, 14), (0, 14, 10), (4, 11, 12), (24, 14, 16), (5, 2, 14), (0, 14, 11), (24, 14, 24), (4, 13, 12), (5, 2, 14), (21, 3, 0), (14, 10, 12), (0, 14, 12), (13, 10, 11), (24, 14, 0), (16, 10, 10), (5, 3, 14), (5, 11, 12), (0, 14, 13), (12, 10, 13), (24, 14, 8), (2, 10, 13), (5, 3, 14), (20, 11, 11), (0, 14, 14), (24, 14, 16), (18, 13, 11), (5, 3, 14), (6, 11, 13), (0, 14, 15), (24, 14, 24), (4, 11, 10), (5, 3, 14), (21, 4, 0), (15, 13, 11), (0, 14, 16), (6, 10, 10), (24, 14, 0), (14, 10, 12), (5, 4, 14), (0, 14, 17), (12, 13, 13), (24, 14, 8), (19, 11, 10), (5, 4, 14), (0, 14, 18), (17, 13, 12), (24, 14, 16), (5, 4, 14), (0, 14, 19), (24, 14, 24), (21, 12, 10), (5, 4, 14), (13, 13, 10), (21, 5, 0), (0, 14, 20), (19, 10, 13), (24, 14, 0), (5, 5, 14), (0, 14, 21), (24, 14, 8), (8, 13, 13), (5, 5, 14), (0, 14, 22), (16, 13, 11), (24, 14, 16), (10, 10, 13), (5, 5, 14), (7, 10, 12), (0, 14, 23), (19, 13, 10), (24, 14, 24), (5, 5, 14), (17, 12, 10), (21, 6, 0), (16, 11, 10), (0, 14, 24), (24, 14, 0), (10, 11, 10), (5, 6, 14), (0, 14, 25), (24, 14, 8), (7, 10, 12), (5, 6, 14), (0, 14, 26), (16, 12, 11), (24, 14, 16), (3, 11, 10), (5, 6, 14), (15, 11, 13), (0, 14, 27), (4, 12, 13), (24, 14, 24), (5, 6, 14), (14, 11, 13), (21, 7, 0), (0, 14, 28), (21, 13, 11), (24, 14, 0), (7, 12, 11), (5, 7, 14), (17, 11, 10), (0, 14, 29), (24, 14, 8), (5, 7, 14), (0, 14, 30), (12, 10, 10), (24, 14, 16), (5, 7, 14), (0, 14, 31), (20, 10, 10), (24, 14, 24), (5, 7, 14), (21, 8, 0), (18, 10, 12), (0, 14, 32), (9, 11, 11), (24, 14, 0), (21, 12, 11), (5, 8, 14), (0, 14, 33), (24, 14, 8), (19, 10, 13), (5, 8, 14), (8, 12, 13), (0, 14, 34), (24, 14, 16), (5, 8, 14), (8, 10, 10), (0, 14, 35), (24, 14, 24), (21, 13, 10), (5, 8, 14), (0, 12, 10), (21, 9, 0), (0, 14, 36), (24, 14, 0), (5, 9, 14), (17, 11, 11), (0, 14, 37), (14, 10, 13), (24, 14, 8), (5, 9, 14), (4, 10, 11), (0, 14, 38), (13, 11, 13), (24, 14, 16), (5, 9, 14), (0, 14, 39), (10, 11, 10), (24, 14, 24), (20, 13, 13), (5, 9, 14), (6, 12, 11), (21, 14, 0), (8, 0, 2769503260), (10, 0, 997841014), (19, 12, 11), (2, 0, 4065997671), (5, 13, 11), (8, 0, 690011675), (15, 11, 11), (8, 0, 540576667), (2, 0, 1618285201), (8, 0, 1123989331), (8, 0, 1914950564), (8, 0, 4213669998), (21, 13, 11), (8, 0, 1529621790), (10, 0, 865446746), (2, 10, 11), (8, 0, 449019059), (16, 13, 11), (8, 0, 906976959), (6, 10, 10), (8, 0, 892028723), (10, 0, 1040131328), (2, 0, 3854135066), (2, 0, 4133925041), (2, 0, 1738396966), (2, 12, 12), (8, 0, 550277338), (10, 0, 1043160697), (2, 1, 1176768057), (10, 1, 2368952475), (8, 12, 11), (2, 1, 2826144967), (8, 1, 1275301297), (10, 1, 2955899422), (2, 1, 2241699318), (12, 11, 10), (8, 1, 537794314), (11, 13, 10), (8, 1, 473021534), (17, 12, 13), (8, 1, 2381227371), (10, 1, 3973380876), (10, 1, 1728990628), (6, 11, 13), (8, 1, 2974252696), (0, 11, 11), (8, 1, 1912236055), (2, 1, 3620744853), (3, 10, 13), (2, 1, 2628426447), (11, 13, 12), (10, 1, 486914414), (16, 11, 12), (10, 1, 1187047173), (14, 12, 11), (2, 2, 3103274804), (13, 10, 10), (8, 2, 3320200805), (8, 2, 3846589389), (1, 13, 13), (2, 2, 2724573159), (10, 2, 1483327425), (2, 2, 1957985324), (14, 13, 12), (10, 2, 1467602691), (8, 2, 3142557962), (2, 13, 12), (2, 2, 2525769395), (8, 2, 3681119483), (8, 12, 11), (10, 2, 1041439413), (10, 2, 1042206298), (2, 2, 527001246), (20, 10, 13), (10, 2, 855860613), (8, 10, 10), (8, 2, 1865979270), (1, 13, 10), (8, 2, 2752636085), (2, 2, 1389650363), (10, 2, 2721642985), (18, 10, 11), (8, 2, 3276518041), (15, 10, 10), (2, 2, 1965130376), (2, 3, 3557111558), (2, 3, 3031574352), (16, 12, 10), (10, 3, 4226755821), (8, 3, 2624879637), (8, 3, 1381275708), (2, 3, 3310620882), (2, 3, 2475591380), (8, 3, 405408383), (2, 3, 2291319543), (0, 12, 12), (8, 3, 4144538489), (2, 3, 3878256896), (6, 11, 10), (10, 3, 2243529248), (10, 3, 561931268), (11, 11, 12), (10, 3, 3076955709), (18, 12, 13), (8, 3, 2019584073), (10, 13, 12), (8, 3, 1712479912), (18, 11, 11), (2, 3, 2804447380), (17, 10, 10), (10, 3, 2957126100), (18, 13, 13), (8, 3, 1368187437), (17, 10, 12), (8, 3, 3586129298), (10, 4, 1229526732), (19, 11, 11), (10, 4, 2759768797), (1, 10, 13), (2, 4, 2112449396), (10, 4, 1212917601), (2, 4, 1524771736), (8, 4, 3146530277), (2, 4, 2997906889), (16, 12, 10), (8, 4, 4135691751), (8, 4, 1960868242), (6, 12, 12), (10, 4, 2775657353), (16, 10, 13), (8, 4, 1451259226), (8, 4, 607382171), (13, 13, 13), (10, 4, 357643050), (2, 4, 2020402776), (8, 5, 2408165152), (13, 12, 10), (2, 5, 806913563), (10, 5, 772591592), (20, 13, 11), (2, 5, 2211018781), (10, 5, 2523354879), (8, 5, 2549720391), (2, 5, 3908178996), (2, 5, 1299171929), (8, 5, 512513885), (10, 5, 2617924552), (1, 12, 13), (8, 5, 390960442), (12, 11, 13), (8, 5, 1248271133), (8, 5, 2114382155), (1, 10, 13), (10, 5, 2078863299), (20, 12, 12), (8, 5, 2857504053), (10, 5, 4271947727), (2, 6, 2238126367), (2, 6, 1544827193), (8, 6, 4094800187), (2, 6, 3461906189), (10, 6, 1812592759), (2, 6, 1506702473), (8, 6, 536175198), (2, 6, 1303821297), (8, 6, 715409343), (2, 6, 4094566992), (14, 10, 11), (2, 6, 1890141105), (0, 13, 13), (2, 6, 3143319360), (10, 7, 696930856), (2, 7, 926450200), (8, 7, 352056373), (20, 13, 11), (10, 7, 3857703071), (8, 7, 3212660135), (5, 12, 10), (10, 7, 3854876250), (21, 12, 11), (8, 7, 3648688720), (2, 7, 2732629817), (4, 10, 12), (10, 7, 2285138643), (18, 10, 13), (2, 7, 2255852466), (2, 7, 2537336944), (3, 10, 13), (2, 7, 4257606405), (10, 8, 3703184638), (7, 11, 10), (10, 8, 2165056562), (8, 8, 2217220568), (19, 10, 12), (8, 8, 2088084496), (15, 13, 10), (8, 8, 443074220), (16, 13, 12), (10, 8, 1298336973), (2, 13, 11), (8, 8, 822378456), (19, 11, 12), (8, 8, 2154711985), (0, 11, 12), (10, 8, 430757325), (2, 12, 10), (2, 8, 2521672196), (10, 9, 532704100), (10, 9, 2519542932), (2, 9, 2451309277), (2, 9, 3957445476), (5, 10, 10), (8, 9, 2583554449), (10, 9, 1149665327), (12, 13, 12), (8, 9, 3053959226), (0, 10, 10), (8, 9, 3693780276), (15, 11, 10), (2, 9, 609918789), (2, 9, 2778221635), (16, 13, 10), (8, 9, 3133754553), (8, 11, 13), (8, 9, 3961507338), (2, 9, 1829237263), (16, 11, 13), (2, 9, 2472519933), (6, 12, 12), (8, 9, 4061630846), (10, 9, 1181684786), (13, 10, 11), (10, 9, 390349075), (8, 9, 2883917626), (10, 9, 3733394420), (10, 12, 12), (2, 9, 3895283827), (20, 10, 11), (2, 9, 2257053750), (10, 9, 2770821931), (18, 10, 13), (2, 9, 477834410), (19, 13, 12), (3, 0, 1), (12, 12, 12), (3, 1, 2), (11, 13, 11), (3, 2, 3), (3, 3, 4), (3, 4, 5), (1, 13, 13), (3, 5, 6), (7, 11, 11), (3, 6, 7), (4, 10, 12), (3, 7, 8), (18, 12, 12), (3, 8, 9), (21, 12, 10), (3, 9, 10)]
# Les caractères autorisées par le programme
CHARSET = string.ascii_letters + string.digits + '_'
# L'état des registres final attendus à la fin
REGISTERS = [0x3ee88722, 0x0ecbdbe2, 0x60b843c4, 0x05da67c7, 0x171ef1e9, 0x52d5b3f7, 0x3ae718c0, 0x8b4aacc2, 0xe5cf78dd, 0x4a848edf, 0x0000008f, 0x04180000, 0x00000000, 0x0000000d, 0x00000000]
# Les deux fonctions de rotations de bits
def _rot_r(value, shift):
return (value >> shift) | (value << (32 - shift))
def _rot_l(value, shift):
return (value << shift) | (value >> (32 - shift))
# Le programme en lui-même
class Program:
def __init__(self, flag):
self.registers = np.zeros(15, dtype=np.uint32)
self.flag = flag
def execute_one(self, instruction):
opcode = instruction[0]
op0 = instruction[1]
op1 = instruction[2]
if opcode == 0:
self.registers[op0] = self.flag[op1]
elif opcode == 1:
self.registers[op0] = op1
elif opcode == 2:
self.registers[op0] ^= op1
elif opcode == 3:
self.registers[op0] ^= self.registers[op1]
elif opcode == 4:
self.registers[op0] |= op1
elif opcode == 5:
self.registers[op0] |= self.registers[op1]
elif opcode == 6:
self.registers[op0] &= op1
elif opcode == 7:
self.registers[op0] &= self.registers[op1]
elif opcode == 8:
self.registers[op0] += op1
elif opcode == 9:
self.registers[op0] += self.registers[op1]
elif opcode == 10:
self.registers[op0] -= op1
elif opcode == 11:
self.registers[op0] -= self.registers[op1]
elif opcode == 12:
self.registers[op0] *= op1
elif opcode == 13:
self.registers[op0] *= self.registers[op1]
elif opcode == 14:
pass
elif opcode == 15:
pass
elif opcode == 16:
self.registers[op0] = _rot_r(self.registers[op0], op1)
elif opcode == 17:
self.registers[op0] = _rot_r(self.registers[op0], self.registers[op1])
elif opcode == 18:
self.registers[op0] = _rot_l(self.registers[op0], op1)
elif opcode == 19:
self.registers[op0] = _rot_l(self.registers[op0], self.registers[op1])
elif opcode == 20:
self.registers[op0] = self.registers[op1]
elif opcode == 21:
self.registers[op0] = 0
elif opcode == 22:
self.registers[op0] >>= op1
elif opcode == 23:
self.registers[op0] >>= self.registers[op1]
elif opcode == 24:
self.registers[op0] <<= op1
elif opcode == 25:
self.registers[op0] <<= self.registers[op1]
else:
raise ValueError("Unknown opcode")
def execute(self, instructions):
for instruction in instructions:
self.execute_one(instruction)
On peut faire plusieurs essais en python et en c++ avec le même input pour voir que l’état final des registres est le même donc à priori pas d’erreur d’implémentation, merci ChatGPT
Etude des registres
Pour voir un peu le comportement des registres, j’ai fait une fonction discover
qui permet de tester des flags différents avec la possibilité de définir un début commun entre les flags et d’afficher les différences entre l’état des registres avec la fonction highlight_diff
def highlight_diff(text1, text2):
output = ""
for i in range(len(text1)):
if text1[i] == text2[i]:
output += text2[i]
else:
output += Fore.RED + Style.DIM + text2[i] + Style.RESET_ALL
return output
def discover(fixed):
fixed_chard = '_'
missing_n = 35 - len(fixed)
flag = "HTB{" + fixed + (fixed_chard * missing_n) + "}"
witness_register = submit_flag(flag.encode())
print(parse_registers(witness_register) + f' # {flag}')
for c in range(16):
garbage = ''.join(random.choices(CHARSET, k=missing_n))
flag = "HTB{" + fixed + garbage + "}"
result_registers = submit_flag(flag.encode())
print(highlight_diff(parse_registers(witness_register), parse_registers(result_registers)) + f' # {flag}')
En faisant ça, on peut soumettre des flags différents et voir si certaines parties des registres réagissent à des changements minimes, exemple avec des flags dont seul le premier caractère est commun :
discover("_")

On voit que le byte 4 du premier registre, autrement dit c’est le premier byte si on lit le registre en little endian, est toujours le même avec la valeur bc
,
En essayant avec des flag qui commencent par les 3 mêmes caractères :
discover("_AB")

On voit 2 choses intéressante :
Maintenant les 3 derniers bytes du registre n°1 sont fixes
Le byte de l’essai d’avant n’a pas changé, c’est toujours
bc
On peut donc émettre l’hypothèse qu’en faisant un brute force caractère par caractère on peut vérifier l’état des registres final et en déduire d’abord le premier caractère, puis le second etc…
Script de résolution
import string
import numpy as np
import warnings
warnings.filterwarnings('ignore') # Pour éliminer les warnings de numpy
INSTRUCTIONS = [(12, 13, 10), (21, 0, 0), (0, 13, 13), (0, 14, 0), (15, 11, 12), (24, 14, 0), (5, 0, 14), (0, 14, 1), (7, 11, 11), (24, 14, 8), (5, 0, 14), (0, 14, 2), (2, 10, 11), (24, 14, 16), (18, 12, 11), (5, 0, 14), (0, 14, 3), (0, 11, 11), (24, 14, 24), (13, 10, 10), (5, 0, 14), (2, 11, 13), (21, 1, 0), (0, 14, 4), (24, 14, 0), (5, 1, 14), (6, 11, 12), (0, 14, 5), (8, 10, 10), (24, 14, 8), (11, 12, 11), (5, 1, 14), (0, 14, 6), (0, 12, 10), (24, 14, 16), (9, 10, 13), (5, 1, 14), (0, 14, 7), (13, 12, 12), (24, 14, 24), (15, 10, 12), (5, 1, 14), (21, 2, 0), (20, 13, 13), (0, 14, 8), (24, 14, 0), (19, 10, 11), (5, 2, 14), (6, 12, 10), (0, 14, 9), (8, 11, 11), (24, 14, 8), (5, 2, 14), (0, 14, 10), (4, 11, 12), (24, 14, 16), (5, 2, 14), (0, 14, 11), (24, 14, 24), (4, 13, 12), (5, 2, 14), (21, 3, 0), (14, 10, 12), (0, 14, 12), (13, 10, 11), (24, 14, 0), (16, 10, 10), (5, 3, 14), (5, 11, 12), (0, 14, 13), (12, 10, 13), (24, 14, 8), (2, 10, 13), (5, 3, 14), (20, 11, 11), (0, 14, 14), (24, 14, 16), (18, 13, 11), (5, 3, 14), (6, 11, 13), (0, 14, 15), (24, 14, 24), (4, 11, 10), (5, 3, 14), (21, 4, 0), (15, 13, 11), (0, 14, 16), (6, 10, 10), (24, 14, 0), (14, 10, 12), (5, 4, 14), (0, 14, 17), (12, 13, 13), (24, 14, 8), (19, 11, 10), (5, 4, 14), (0, 14, 18), (17, 13, 12), (24, 14, 16), (5, 4, 14), (0, 14, 19), (24, 14, 24), (21, 12, 10), (5, 4, 14), (13, 13, 10), (21, 5, 0), (0, 14, 20), (19, 10, 13), (24, 14, 0), (5, 5, 14), (0, 14, 21), (24, 14, 8), (8, 13, 13), (5, 5, 14), (0, 14, 22), (16, 13, 11), (24, 14, 16), (10, 10, 13), (5, 5, 14), (7, 10, 12), (0, 14, 23), (19, 13, 10), (24, 14, 24), (5, 5, 14), (17, 12, 10), (21, 6, 0), (16, 11, 10), (0, 14, 24), (24, 14, 0), (10, 11, 10), (5, 6, 14), (0, 14, 25), (24, 14, 8), (7, 10, 12), (5, 6, 14), (0, 14, 26), (16, 12, 11), (24, 14, 16), (3, 11, 10), (5, 6, 14), (15, 11, 13), (0, 14, 27), (4, 12, 13), (24, 14, 24), (5, 6, 14), (14, 11, 13), (21, 7, 0), (0, 14, 28), (21, 13, 11), (24, 14, 0), (7, 12, 11), (5, 7, 14), (17, 11, 10), (0, 14, 29), (24, 14, 8), (5, 7, 14), (0, 14, 30), (12, 10, 10), (24, 14, 16), (5, 7, 14), (0, 14, 31), (20, 10, 10), (24, 14, 24), (5, 7, 14), (21, 8, 0), (18, 10, 12), (0, 14, 32), (9, 11, 11), (24, 14, 0), (21, 12, 11), (5, 8, 14), (0, 14, 33), (24, 14, 8), (19, 10, 13), (5, 8, 14), (8, 12, 13), (0, 14, 34), (24, 14, 16), (5, 8, 14), (8, 10, 10), (0, 14, 35), (24, 14, 24), (21, 13, 10), (5, 8, 14), (0, 12, 10), (21, 9, 0), (0, 14, 36), (24, 14, 0), (5, 9, 14), (17, 11, 11), (0, 14, 37), (14, 10, 13), (24, 14, 8), (5, 9, 14), (4, 10, 11), (0, 14, 38), (13, 11, 13), (24, 14, 16), (5, 9, 14), (0, 14, 39), (10, 11, 10), (24, 14, 24), (20, 13, 13), (5, 9, 14), (6, 12, 11), (21, 14, 0), (8, 0, 2769503260), (10, 0, 997841014), (19, 12, 11), (2, 0, 4065997671), (5, 13, 11), (8, 0, 690011675), (15, 11, 11), (8, 0, 540576667), (2, 0, 1618285201), (8, 0, 1123989331), (8, 0, 1914950564), (8, 0, 4213669998), (21, 13, 11), (8, 0, 1529621790), (10, 0, 865446746), (2, 10, 11), (8, 0, 449019059), (16, 13, 11), (8, 0, 906976959), (6, 10, 10), (8, 0, 892028723), (10, 0, 1040131328), (2, 0, 3854135066), (2, 0, 4133925041), (2, 0, 1738396966), (2, 12, 12), (8, 0, 550277338), (10, 0, 1043160697), (2, 1, 1176768057), (10, 1, 2368952475), (8, 12, 11), (2, 1, 2826144967), (8, 1, 1275301297), (10, 1, 2955899422), (2, 1, 2241699318), (12, 11, 10), (8, 1, 537794314), (11, 13, 10), (8, 1, 473021534), (17, 12, 13), (8, 1, 2381227371), (10, 1, 3973380876), (10, 1, 1728990628), (6, 11, 13), (8, 1, 2974252696), (0, 11, 11), (8, 1, 1912236055), (2, 1, 3620744853), (3, 10, 13), (2, 1, 2628426447), (11, 13, 12), (10, 1, 486914414), (16, 11, 12), (10, 1, 1187047173), (14, 12, 11), (2, 2, 3103274804), (13, 10, 10), (8, 2, 3320200805), (8, 2, 3846589389), (1, 13, 13), (2, 2, 2724573159), (10, 2, 1483327425), (2, 2, 1957985324), (14, 13, 12), (10, 2, 1467602691), (8, 2, 3142557962), (2, 13, 12), (2, 2, 2525769395), (8, 2, 3681119483), (8, 12, 11), (10, 2, 1041439413), (10, 2, 1042206298), (2, 2, 527001246), (20, 10, 13), (10, 2, 855860613), (8, 10, 10), (8, 2, 1865979270), (1, 13, 10), (8, 2, 2752636085), (2, 2, 1389650363), (10, 2, 2721642985), (18, 10, 11), (8, 2, 3276518041), (15, 10, 10), (2, 2, 1965130376), (2, 3, 3557111558), (2, 3, 3031574352), (16, 12, 10), (10, 3, 4226755821), (8, 3, 2624879637), (8, 3, 1381275708), (2, 3, 3310620882), (2, 3, 2475591380), (8, 3, 405408383), (2, 3, 2291319543), (0, 12, 12), (8, 3, 4144538489), (2, 3, 3878256896), (6, 11, 10), (10, 3, 2243529248), (10, 3, 561931268), (11, 11, 12), (10, 3, 3076955709), (18, 12, 13), (8, 3, 2019584073), (10, 13, 12), (8, 3, 1712479912), (18, 11, 11), (2, 3, 2804447380), (17, 10, 10), (10, 3, 2957126100), (18, 13, 13), (8, 3, 1368187437), (17, 10, 12), (8, 3, 3586129298), (10, 4, 1229526732), (19, 11, 11), (10, 4, 2759768797), (1, 10, 13), (2, 4, 2112449396), (10, 4, 1212917601), (2, 4, 1524771736), (8, 4, 3146530277), (2, 4, 2997906889), (16, 12, 10), (8, 4, 4135691751), (8, 4, 1960868242), (6, 12, 12), (10, 4, 2775657353), (16, 10, 13), (8, 4, 1451259226), (8, 4, 607382171), (13, 13, 13), (10, 4, 357643050), (2, 4, 2020402776), (8, 5, 2408165152), (13, 12, 10), (2, 5, 806913563), (10, 5, 772591592), (20, 13, 11), (2, 5, 2211018781), (10, 5, 2523354879), (8, 5, 2549720391), (2, 5, 3908178996), (2, 5, 1299171929), (8, 5, 512513885), (10, 5, 2617924552), (1, 12, 13), (8, 5, 390960442), (12, 11, 13), (8, 5, 1248271133), (8, 5, 2114382155), (1, 10, 13), (10, 5, 2078863299), (20, 12, 12), (8, 5, 2857504053), (10, 5, 4271947727), (2, 6, 2238126367), (2, 6, 1544827193), (8, 6, 4094800187), (2, 6, 3461906189), (10, 6, 1812592759), (2, 6, 1506702473), (8, 6, 536175198), (2, 6, 1303821297), (8, 6, 715409343), (2, 6, 4094566992), (14, 10, 11), (2, 6, 1890141105), (0, 13, 13), (2, 6, 3143319360), (10, 7, 696930856), (2, 7, 926450200), (8, 7, 352056373), (20, 13, 11), (10, 7, 3857703071), (8, 7, 3212660135), (5, 12, 10), (10, 7, 3854876250), (21, 12, 11), (8, 7, 3648688720), (2, 7, 2732629817), (4, 10, 12), (10, 7, 2285138643), (18, 10, 13), (2, 7, 2255852466), (2, 7, 2537336944), (3, 10, 13), (2, 7, 4257606405), (10, 8, 3703184638), (7, 11, 10), (10, 8, 2165056562), (8, 8, 2217220568), (19, 10, 12), (8, 8, 2088084496), (15, 13, 10), (8, 8, 443074220), (16, 13, 12), (10, 8, 1298336973), (2, 13, 11), (8, 8, 822378456), (19, 11, 12), (8, 8, 2154711985), (0, 11, 12), (10, 8, 430757325), (2, 12, 10), (2, 8, 2521672196), (10, 9, 532704100), (10, 9, 2519542932), (2, 9, 2451309277), (2, 9, 3957445476), (5, 10, 10), (8, 9, 2583554449), (10, 9, 1149665327), (12, 13, 12), (8, 9, 3053959226), (0, 10, 10), (8, 9, 3693780276), (15, 11, 10), (2, 9, 609918789), (2, 9, 2778221635), (16, 13, 10), (8, 9, 3133754553), (8, 11, 13), (8, 9, 3961507338), (2, 9, 1829237263), (16, 11, 13), (2, 9, 2472519933), (6, 12, 12), (8, 9, 4061630846), (10, 9, 1181684786), (13, 10, 11), (10, 9, 390349075), (8, 9, 2883917626), (10, 9, 3733394420), (10, 12, 12), (2, 9, 3895283827), (20, 10, 11), (2, 9, 2257053750), (10, 9, 2770821931), (18, 10, 13), (2, 9, 477834410), (19, 13, 12), (3, 0, 1), (12, 12, 12), (3, 1, 2), (11, 13, 11), (3, 2, 3), (3, 3, 4), (3, 4, 5), (1, 13, 13), (3, 5, 6), (7, 11, 11), (3, 6, 7), (4, 10, 12), (3, 7, 8), (18, 12, 12), (3, 8, 9), (21, 12, 10), (3, 9, 10)]
REGISTERS = [0x3ee88722, 0x0ecbdbe2, 0x60b843c4, 0x05da67c7, 0x171ef1e9, 0x52d5b3f7, 0x3ae718c0, 0x8b4aacc2, 0xe5cf78dd, 0x4a848edf, 0x0000008f, 0x04180000, 0x00000000, 0x0000000d, 0x00000000]
CHARSET = string.ascii_letters + string.digits + '_
class Program:
def __init__(self, flag):
self.registers = np.zeros(15, dtype=np.uint32)
self.flag = flag
def execute_one(self, instruction):
opcode = instruction[0]
op0 = instruction[1]
op1 = instruction[2]
if opcode == 0:
self.registers[op0] = self.flag[op1]
elif opcode == 1:
self.registers[op0] = op1
elif opcode == 2:
self.registers[op0] ^= op1
elif opcode == 3:
self.registers[op0] ^= self.registers[op1]
elif opcode == 4:
self.registers[op0] |= op1
elif opcode == 5:
self.registers[op0] |= self.registers[op1]
elif opcode == 6:
self.registers[op0] &= op1
elif opcode == 7:
self.registers[op0] &= self.registers[op1]
elif opcode == 8:
self.registers[op0] += op1
elif opcode == 9:
self.registers[op0] += self.registers[op1]
elif opcode == 10:
self.registers[op0] -= op1
elif opcode == 11:
self.registers[op0] -= self.registers[op1]
elif opcode == 12:
self.registers[op0] *= op1
elif opcode == 13:
self.registers[op0] *= self.registers[op1]
elif opcode == 14:
pass
elif opcode == 15:
pass
elif opcode == 16:
self.registers[op0] = _rot_r(self.registers[op0], op1)
elif opcode == 17:
self.registers[op0] = _rot_r(self.registers[op0], self.registers[op1])
elif opcode == 18:
self.registers[op0] = _rot_l(self.registers[op0], op1)
elif opcode == 19:
self.registers[op0] = _rot_l(self.registers[op0], self.registers[op1])
elif opcode == 20:
self.registers[op0] = self.registers[op1]
elif opcode == 21:
self.registers[op0] = 0
elif opcode == 22:
self.registers[op0] >>= op1
elif opcode == 23:
self.registers[op0] >>= self.registers[op1]
elif opcode == 24:
self.registers[op0] <<= op1
elif opcode == 25:
self.registers[op0] <<= self.registers[op1]
else:
raise ValueError("Unknown opcode")
def execute(self, instructions):
for instruction in instructions:
self.execute_one(instruction)
def _rot_r(value, shift):
return (value >> shift) | (value << (32 - shift))
def _rot_l(value, shift):
return (value << shift) | (value >> (32 - shift))
import random
from colorama import Fore, Style
from chall import Program, CHARSET, INSTRUCTIONS, REGISTERS
def solve():
flag = ''
expected_state = b''.join([register.to_bytes(4, byteorder='little') for register in REGISTERS])
for i in range(35):
missing_n = 35 - len(flag) - 1
for c in CHARSET:
attempt_flag = "HTB{" + flag + c + ('_' * missing_n) + "}"
program = Program(attempt_flag.encode())
program.execute(INSTRUCTIONS)
current_state = b''.join([int(register).to_bytes(4, byteorder='little') for register in program.registers])
if expected_state[:i+1] == current_state[:i+1]:
flag += c
break
print(f"Flag: HTB{{{flag}}}")
if __name__ == '__main__':
solve()
Dernière mise à jour
Cet article vous a-t-il été utile ?