Skip to content

Instantly share code, notes, and snippets.

@pafmaf
Created June 27, 2016 16:13
Show Gist options
  • Save pafmaf/cf7f44de76b65a5edb130fa928697bea to your computer and use it in GitHub Desktop.
Save pafmaf/cf7f44de76b65a5edb130fa928697bea to your computer and use it in GitHub Desktop.
Decoding .fz board files.
// Decoding an .fz file. You still need the key of course.
// https://en.wikipedia.org/wiki/RC6 here you can read it all up.
// Looking at the paper the algo is straight forward, not sure about endianness.
// This will put out some .bin file you would decompress using zlib.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
// Put your key here.
// uint32_t keylength = 2*r + 4; // i.e. buf[0..2r+3]
uint32_t S[44] = {0};
static inline uint32_t rotl32(uint32_t a, int32_t b) {
return (a << b) | (a >> (32 - b));
}
static void decode_fz(uint8_t *source, uint8_t *dest, size_t size) {
// Along the lines of http://people.csail.mit.edu/rivest/pubs/RRSY98.pdf
// (page 3, 2.2)
int32_t logw = 5;
uint32_t r = 20;
uint32_t A = 0;
uint32_t B = 0;
uint32_t C = 0;
uint32_t D = 0;
uint8_t currentByte;
uint8_t ibuf[16] = {0}; // you'll see
// RC6 algo from the paper, basically 1:1
for (int pos = 0; pos < size; ++pos) {
B = B + S[0];
D = D + S[1];
for (uint32_t i = 1; i < (r + 1); ++i) // loop offset by 1
{
uint32_t t = rotl32(B * (2 * B + 1), logw);
uint32_t u = rotl32(D * (2 * D + 1), logw);
A = rotl32(A ^ t, (int32_t)u) + S[2 * i];
C = rotl32(C ^ u, (int32_t)t) + S[2 * i + 1];
uint32_t tmp = A;
A = B;
B = C;
C = D;
D = tmp;
}
A = A + S[2 * r + 2];
C = C + S[2 * r + 3]; // not used I guess
// rolling over the the uint8_t string
// buf[pos] xor A -> is our resulting byte
currentByte = source[pos];
dest[pos] = ((uint8_t)(currentByte ^ (A & 0xFF)));
// pushing in a stream of buf[pos] chars 'from the right'
// and shift whole array 8 bits to the left
for (uint32_t i = 0; i < 15; ++i) {
ibuf[i] = ibuf[i + 1];
}
ibuf[15] = currentByte;
// align 4 consequent int32s to that buffer
// (A, B, C, D) = (buf[0], buf[1], buf[2], buf[3])
// byte order?!
A = ibuf[0] | ibuf[1] << 8 | ibuf[2] << 16 | ibuf[3] << 24;
B = ibuf[4] | ibuf[5] << 8 | ibuf[6] << 16 | ibuf[7] << 24;
C = ibuf[8] | ibuf[9] << 8 | ibuf[10] << 16 | ibuf[11] << 24;
D = ibuf[12] | ibuf[13] << 8 | ibuf[14] << 16 | ibuf[15] << 24;
}
}
int main() {
FILE *f_fz = fopen("some.fz", "rb"); // source file
FILE *f_bin = fopen("some.bin", "wb"); // output
// read fz file into buffer
fseek(f_fz, 0, SEEK_END);
size_t fsize = ftell(f_fz);
rewind(f_fz);
// alloc
uint8_t *buf_fz = new uint8_t[fsize];
uint8_t *buf_bin = new uint8_t[fsize];
// read & decode
fread(buf_fz, sizeof(uint8_t), fsize, f_fz);
decode_fz(buf_fz, buf_bin, fsize);
// write back
fwrite(buf_bin, sizeof(uint8_t), fsize, f_bin);
// free stuff
fclose(f_fz);
fclose(f_bin);
delete[] buf_fz;
delete[] buf_bin;
}
#!/usr/bin/env python3
"""
This is for splitting up the resulting stream by decoding the RC6 file
with .fz ending. The key is probably the weird part here.
The stream is split in two parts (potentially something like the contents
followed by some content description) at an offset specified by the last 4 bytes
interpreted as an int32.
"""
from zlib import decompress as deco
buf = str()
with open("some.bin", "rb") as f:
buf = f.read()
# length stored as last 4 bytes LE (int)
descr_len = int.from_bytes(buf[-4:], byteorder='little')
(content, descr) = (deco(buf[4:-descr_len+4]), deco(buf[-descr_len+4:]))
print(str(content, 'utf-8'))
@my6010
Copy link

my6010 commented Jul 20, 2019

Have you resolved the data structure of the Asus.fz file format?I need to know the data structure of the .fz file, which is very important to me, if you know the trouble you tell me!

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