Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!python3
- #
- # TFC CTF 2025 - Reverse: font league
- #
- # *** Idea:
- # - Analysis done with https://fontdrop.info/
- # - TTF file has ligature glyphs that are composed of a base and a composite glyph
- # - glyphs with IDs <1000 are of interest
- # - frequency analysis shows that glyph IDs 19-28 and 68-73 correspond to hex digits
- # - looking through glyphs, several print "O", e.g. 2723
- # - take the base and composite glyph of ligature glyph 2723
- # - recursively decompose into "atomic" glyphs with ID <1000
- # - get the atomic characters, translate into hex digits, wrap as flag
- #
- # *** Run it:
- # (venv-TFCCTF2025) neuland% python3 9atomglyph.py 2723
- # Atomic glyph IDs in correct order:
- # [20, 73, 27, 28, 68, 28, 24, 26, 68, 19, 27, 20, 25, 72, 22, 69, 72, 68, 22, 73, 68, 19, 21, 25, 70, 71, 28, 68, 23, 26, 70, 73, 20, 27, 20, 73, 69, 21, 70, 19, 72, 19, 70, 28, 72, 28, 23, 23, 21, 68, 21, 70, 26, 27, 22, 69, 19, 20, 70, 19, 27, 22, 71, 21]
- #
- # Translated atomic glyphs to characters:
- # 1f89a957a0816e3bea3fa026cd9a47cf181fb2c0e0c9e9442a2c783b01c083d2
- #
- # *** Flag:
- # TFCCTF{1f89a957a0816e3bea3fa026cd9a47cf181fb2c0e0c9e9442a2c783b01c083d2}
- #
- # Greetings from hubertf to the MadMonday CTF Team
- #
- import sys
- from fontTools.ttLib import TTFont
- glyph_id_to_char = {
- 19: '0',
- 20: '1',
- 21: '2',
- 22: '3',
- 23: '4',
- 24: '5',
- 25: '6',
- 26: '7',
- 27: '8',
- 28: '9',
- 68: 'a',
- 69: 'b',
- 70: 'c',
- 71: 'd',
- 72: 'e',
- 73: 'f',
- }
- def load_ligature_map(font):
- gsub = font['GSUB'].table
- lig_map = {}
- for lookup in gsub.LookupList.Lookup:
- if lookup.LookupType == 4: # Ligature substitution
- for subtable in lookup.SubTable:
- if subtable.__class__.__name__ == "LigatureSubst":
- ligatures = subtable.ligatures
- for base_glyph_name, lig_list in ligatures.items():
- base_gid = font.getGlyphID(base_glyph_name)
- for lig in lig_list:
- lig_gid = font.getGlyphID(lig.LigGlyph)
- component_gids = [font.getGlyphID(c) for c in getattr(lig, 'Components', getattr(lig, 'Component', []))]
- lig_map[lig_gid] = (base_gid, component_gids)
- return lig_map
- def resolve_glyph(gid, lig_map, atomic_threshold=1000):
- """Rekursiv Ligatur auflösen und atomare Glyphen in korrekter Reihenfolge zurückgeben."""
- if gid < atomic_threshold or gid not in lig_map:
- return [gid] # atomare Glyphe als Liste
- base_gid, components = lig_map[gid]
- result = []
- # Zuerst Basis rekursiv auflösen (Reihenfolge wichtig)
- result.extend(resolve_glyph(base_gid, lig_map, atomic_threshold))
- # Dann alle Komponenten in Reihenfolge rekursiv auflösen
- for comp_gid in components:
- result.extend(resolve_glyph(comp_gid, lig_map, atomic_threshold))
- return result
- def main():
- font_path = "font-leagues/Arial-custom.ttf"
- font = TTFont(font_path)
- lig_map = load_ligature_map(font)
- if len(sys.argv) < 2:
- print("Usage: python3 6list-list.py <ligature_glyph_id>")
- return
- try:
- start_gid = int(sys.argv[1])
- except ValueError:
- print("Please provide a valid integer ligature glyph ID.")
- return
- if start_gid not in lig_map:
- print(f"Ligature glyph ID {start_gid} not found in the font's ligature map.")
- return
- atomic_glyphs_in_order = resolve_glyph(start_gid, lig_map)
- print("Atomic glyph IDs in correct order:")
- print(atomic_glyphs_in_order)
- # Zeichenkette aus der Mapping-Tabelle
- translated = "".join(glyph_id_to_char.get(gid, '?') for gid in atomic_glyphs_in_order)
- print("\nTranslated atomic glyphs to characters:")
- print(translated)
- if __name__ == "__main__":
- main()
Advertisement
Comments
-
- ⭐ Changelly Profit Exploit Documentation ⭐
- https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=lijtoggmdu
- This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
- The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
- Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment