50 lines
1.5 KiB
Python
50 lines
1.5 KiB
Python
"""
|
|
EXAMPLE: Hack.lu 2020 — "Russian threesome" (RE, 500p, 5 solves)
|
|
https://github.com/p4-team/ctf/tree/master/2020-10-23-hacklu/russian_threesome
|
|
|
|
VULN: a balanced-ternary drum-machine dumps two permutation sectors `s7` (40
|
|
bytes of ciphertext) and `s17` (a 256-byte S-box). The flag is recovered by
|
|
repeatedly applying the INVERSE permutation to each `s7` byte until the sum of
|
|
the resulting bytes equals the number of applications (a fixed-point/self-
|
|
consistency check). Final bytes decode as CP1251 (Russian proverb).
|
|
|
|
Run:
|
|
cd /home/code/ctfkit
|
|
python3 examples/russian_threesome/solve.py
|
|
Expected flag: "Кто хочет много знать, тому мало спать."
|
|
"""
|
|
import os
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
def main():
|
|
s7 = [int(c, 16) for c in open(f"{HERE}/s7").read().split()]
|
|
s17 = [int(c, 16) for c in open(f"{HERE}/s17").read().split()]
|
|
s17 = s17[1::2]
|
|
inverse = [0] * 256
|
|
for i, j in enumerate(s17):
|
|
inverse[j] = i
|
|
|
|
for potential_sum in range(256 * len(s7)):
|
|
flag = []
|
|
for ch in s7:
|
|
c = ch
|
|
for _ in range(potential_sum):
|
|
c = inverse[c]
|
|
flag.append(c)
|
|
if sum(flag) == potential_sum:
|
|
b = bytes(flag)
|
|
try:
|
|
flag_str = b.decode("cp1251")
|
|
except Exception:
|
|
flag_str = b.decode("latin1")
|
|
print("FLAG =", flag_str)
|
|
return flag_str
|
|
print("no flag found")
|
|
return None
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|