Skip to content

Instantly share code, notes, and snippets.

@dungsaga
Last active April 3, 2024 09:37
Show Gist options
  • Save dungsaga/ab8d2379bb566c9925b27df3bc82ca8b to your computer and use it in GitHub Desktop.
Save dungsaga/ab8d2379bb566c9925b27df3bc82ca8b to your computer and use it in GitHub Desktop.
deobfuscate odttf file (extracted from M$ XPS file)
const purpose = "Purpose: deobfuscate odttf file (extracted from M$ XPS file)"
const usage = "Usage: node deobfuscate-odttf-in-xps.js <guid-obfuscated-font-file.odttf> [<output-file.ttf>]"
const obfuscatedStartOffset = 0 //start of obfuscated bytes in font file
const obfuscatedEndOffset = 32 //start of obfuscated bytes in font file
const guidSize = 32 // length of GUID string (only hex characters included)
const fs = require('fs')
const path = require('path')
//process.argv[0] is path to node.js
//process.argv[1] is path to this script
const fontFilepath = process.argv[2]
if (fontFilepath == null) {
console.warn(purpose)
console.warn(usage)
return
}
const fontFilename = path.basename(fontFilepath)
const guid = fontFilename.replace(/-/g, "").replace(/\..+$/, "")
if (guid.length !== guidSize) {
console.warn(guid, "Error: Cannot extract GUID from font filename (ex: A5C0272A-DD4C-401C-8661-BEAD77E57818.odttf)")
return
}
// get hex numbers from GUID
const hexStrings = guid.replace(/(..)/g,"$1 ").trim().split(" ")
const hexNumbers = hexStrings.map((hexString) => parseInt(hexString, 16))
hexNumbers.reverse()
// deobfuscate by XORing obfuscated bytes with hexNumbers
const buf = fs.readFileSync(fontFilepath)
const obfuscatedBytes = buf.slice(obfuscatedStartOffset, obfuscatedEndOffset)
const recoveredBytes = obfuscatedBytes.map((byte, i) => byte ^ hexNumbers[i % hexNumbers.length] )
// write result to a ttf file
const out = Buffer.concat([
buf.slice(0, obfuscatedStartOffset),
recoveredBytes,
buf.slice(obfuscatedEndOffset)
])
const outputFilepath = process.argv[3] || fontFilepath + '.ttf'
fs.writeFile(
outputFilepath,
out,
{ encoding: null },
(error) => { if (error) throw error; }
)
@dungsaga
Copy link
Author

based on function xps_deobfuscate_font_resource in https://mupdf.com/docs/browse/source/xps/xps-glyphs.c.html

@dlazesz
Copy link

dlazesz commented Feb 14, 2019

Thx!

BTW I've created a Python 3 version! Feel free to use!

#!/usr/bin/env python3

import os
import sys

fn_in = sys.argv[1]
fn_out = os.path.splitext(sys.argv[1])[0] + '.ttf'
print(fn_out)
# Parse
key = os.path.splitext(os.path.basename(fn_in))[0].replace('-', '')
# Convert to Int reversed
key_int = [int(key[i-2:i], 16) for i in range(32, 0, -2)]

with open(fn_in, 'rb') as fh_in, open(fn_out, 'wb') as fh_out:
	cont = fh_in.read()
	fh_out.write(bytes(b ^ key_int[i % len(key_int)] for i, b in enumerate(cont[:32])))
	fh_out.write(cont[32:])

usage: deobfuscate.py U-U-I-D.odttf
returns: U-U-I-D.ttf

@sicklittlemonkey
Copy link

C# version adapted from http://blogs.microsoft.co.il/tamir/2008/04/17/converting-fixeddocument-xpsdocument-too-to-flowdocument/

		public static void DeobfuscateXpsFont(string XpsFontFilename, string TtfOutputFilename)
		{
			using (FileStream stm = new FileStream(XpsFontFilename, FileMode.Open))
			using (FileStream fs = new FileStream(TtfOutputFilename, FileMode.Create))
			{
				byte[] dta = new byte[stm.Length];
				stm.Read(dta, 0, dta.Length);
				//if (font.IsObfuscated)
				{
					string guid = new Guid(XpsFontFilename.Split('.')[0]).ToString("N");
					byte[] guidBytes = new byte[16];
					for (int i = 0; i < guidBytes.Length; i++)
					{
						guidBytes[i] = Convert.ToByte(guid.Substring(i * 2, 2), 16);
					}

					for (int i = 0; i < 32; i++)
					{
						int gi = guidBytes.Length - (i % guidBytes.Length) - 1;
						dta[i] ^= guidBytes[gi];
					}
				}
				fs.Write(dta, 0, dta.Length);
			}
		}

@dungsaga
Copy link
Author

dungsaga commented Nov 7, 2019

BTW I've created a Python 3 version! Feel free to use!

Thanks @dlazesz. The Python 3 version is much cleaner.

@3alisaki
Copy link

Thanks @dlazesz. for Python version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment