Skip to content

Instantly share code, notes, and snippets.

@JayFoxRox

JayFoxRox/xtf.py Secret

Last active August 22, 2017 20:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JayFoxRox/3749698d1ae590608433672bffecba5a to your computer and use it in GitHub Desktop.
Save JayFoxRox/3749698d1ae590608433672bffecba5a to your computer and use it in GitHub Desktop.
XTF parser
#!/bin/env python3
import sys
import struct
import os
print('<?xml version="1.0" standalone="yes"?>')
print('<svg width="100%" height="100%" version="1.1" xmlns = "http://www.w3.org/2000/svg">')
print(' <defs>')
print(' <font id="font" horiz-adv-x="1000">')
print(' <font-face font-family="Super Sans" font-weight="normal" font-style="italic"')
print(' units-per-em="1000" cap-height="600" x-height="400"')
print(' ascent="700" descent="300"')
print(' alphabetic="0" mathematical="350" ideographic="400" hanging="500">')
print(' <font-face-src>')
print(' <font-face-name name="Super Sans Italic"/>')
print(' </font-face-src>')
print(' </font-face>')
print(' <missing-glyph><path d="M0,0h200v200h-200z"/></missing-glyph>')
#print(' <glyph unicode="@"><!-- Outline of @ glyph --></glyph>')
with open(sys.argv[1], 'rb') as f:
magic = f.read(4)
string_len = struct.unpack("I", f.read(4))[0]
string = f.read(string_len).decode('ascii')
# https://msdn.microsoft.com/en-us/library/dd144956%28v=vs.85%29.aspx
cursor = f.tell()
cbThis = struct.unpack("I", f.read(4))[0] #FIXME: Is this the one being exploited?! If so, log something!
flAccel = struct.unpack("I", f.read(4))[0]
assert(flAccel == 0)
cGlyphsSupported = struct.unpack("I", f.read(4))[0]
print("<!-- " + str(cGlyphsSupported) + " glyphs supported -->")
cRanges = struct.unpack("I", f.read(4))[0]
ranges = []
for i in range(cRanges):
wcLow = struct.unpack("H", f.read(2))[0]
cGlyphs = struct.unpack("H", f.read(2))[0]
ranges.append((wcLow, cGlyphs))
assert(f.tell() == (cursor + cbThis))
for i in range(cGlyphsSupported):
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd374209(v=vs.85).aspx
#FIXME: Parse these!
f.read(4)
f.read(4)
f.read(8)
f.read(4)
f.read(4)
offset = struct.unpack("I", f.read(4))[0]
glyphCount = 0
for r in ranges:
print("<!-- Decoding " + str(r[1]) + " symbols -->")
glyphCount += r[1]
for c in range(r[0], r[0] + r[1]):
symbol = struct.pack('H', c).decode("utf-16")
print("<!-- Decoding symbol " + str(c) + ": \"" + symbol + "\" -->")
symbol = "&#x%04X;" % c
index_count = struct.unpack("H", f.read(2))[0]
vertex_count = struct.unpack("H", f.read(2))[0]
indices = []
for i in range(index_count):
indices.append(struct.unpack("H", f.read(2))[0])
vertices = []
for i in range(vertex_count):
vertices.append((struct.unpack("f", f.read(4))[0], struct.unpack("f", f.read(4))[0]))
def strf(f):
return str(int(f * 1000))
path = ""
assert(len(indices) % 3 == 0)
for i in range(len(indices) // 3):
path += "M " + strf(vertices[indices[i*3+0]][0]) + " " + strf(vertices[indices[i*3+0]][1]) + " "
path += "L " + strf(vertices[indices[i*3+1]][0]) + " " + strf(vertices[indices[i*3+1]][1]) + " "
path += "L " + strf(vertices[indices[i*3+2]][0]) + " " + strf(vertices[indices[i*3+2]][1]) + " "
path += "z "
print(' <glyph unicode="' + symbol + '" horiz-adv-x="300" d="' + path + '"></glyph>')
# Hack to only export first range
if False:
f.seek(0, os.SEEK_END)
break
cursor = f.tell()
f.seek(0, os.SEEK_END)
assert(f.tell() == cursor)
print(' <!-- more glyphs -->')
print(' </font>')
print(' </defs>')
print('</svg>')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment