Metagaming
Dernière mise à jour
Cet article vous a-t-il Γ©tΓ© utile ?
Dernière mise à jour
Cet article vous a-t-il Γ©tΓ© utile ?
CatΓ©gorie: Reverse DifficultΓ©: hard Flag: HTB{m4n_1_l0v4_cXX_TeMpl4t35_9fb60c17b0}
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
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β¦
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()