-
-
Save v3l0c1r4pt0r/9acdbca0792cc1c8eece039b6246a537 to your computer and use it in GitHub Desktop.
// compile with: | |
// $ gcc -o smaz smaz.c -Iucl-1.03/include -lucl -Lucl-1.03/build/src/.libs | |
// or if you have ucl in system: | |
// $ gcc -o smaz smaz.c -lucl | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <arpa/inet.h> | |
#include <ucl/ucl.h> | |
#define SMAZ 0x534d415a | |
#define OUTLEN 0x50000 * 20 | |
typedef struct { | |
uint32_t magic; | |
uint32_t unknown; | |
uint32_t unknown1; | |
uint32_t size; | |
} smaz_hdr_t; | |
int main() { | |
/* read header */ | |
smaz_hdr_t header; | |
if (fread(&header, 1, sizeof(header), stdin) != sizeof(header)) { | |
perror("fread(header)"); | |
return 1; | |
} | |
/* check magic */ | |
if (header.magic != htonl(SMAZ)) { | |
fprintf(stderr, "error: wrong magic: '%.4s'\n", header.magic); | |
return 1; | |
} | |
uint32_t flags = header.unknown1; | |
size_t compressed_size = ntohl(header.size); | |
do { | |
/* read rest of file to buffer */ | |
void *buffer = malloc(header.size); | |
//compressed_size -= sizeof(header); | |
size_t to_read = compressed_size; | |
size_t done = 0; | |
fprintf(stderr, "info: I am about to read %u bytes\n", to_read); | |
while (to_read > 0) { | |
done = fread(buffer, 1, to_read, stdin); | |
fprintf(stderr, "info: done %u bytes\n", done); | |
if (done == 0) { | |
perror("fread(buffer)"); | |
fprintf(stderr, "info: %u yet to be read, but got nothing\n", to_read); | |
break; | |
//return 1; | |
} | |
to_read -= done; | |
fprintf(stderr, "info: %u yet to be read\n", to_read); | |
} | |
/* decompress */ | |
void *cursor = buffer; | |
unsigned int outlen = compressed_size + (compressed_size / 8) + 256; | |
uint8_t *output = (uint8_t*) calloc(outlen, 1); | |
int status = ucl_nrv2e_decompress_safe_8(buffer, compressed_size, output, &outlen, NULL); | |
if (status != 0) { | |
fprintf(stderr, "error: decompression failed with %x\n", status); | |
/* intentionally do not return, something was done either way */ | |
} | |
fprintf(stderr, "info: I am about to write %u bytes\n", outlen); | |
if (fwrite(output, 1, outlen, stdout) != outlen) { | |
perror("fwrite"); | |
return 1; | |
} | |
if (fread(&flags, 1, sizeof(flags), stdin) != sizeof(flags)) { | |
perror("fread(flags)"); | |
return 1; | |
} | |
flags = ntohl(flags); | |
fprintf(stderr, "info: flags are %u\n", flags); | |
if (flags == 0) { | |
break; | |
} | |
if (fread(&compressed_size, 1, sizeof(uint32_t), stdin) != sizeof(uint32_t)) { | |
perror("fread(compressed_size)"); | |
return 1; | |
} | |
compressed_size = ntohl(compressed_size); | |
fprintf(stderr, "info: next chunk compressed size is %u\n", compressed_size); | |
free(buffer); | |
} while (flags != 0); | |
/* clean up */ | |
return 0; | |
} |
and this line is not very safe too:
https://gist.github.com/v3l0c1r4pt0r/9acdbca0792cc1c8eece039b6246a537#file-smaz-c-L30
I'm getting segfault:
# ./smaz < /dev/urandom > out.raw
Segmentation fault (core dumped)
but first you need to extract SMAZ from .PKG file. is there a programmatical way?
Unfortunately, dd only. I started writing Python library for that when hacking lkv for the first time, but never finished it. All that is done is as far as I remember ITEPKG itself, not SMEDIA, nor SMAZ. Should be helpful a little bit: https://github.com/v3l0c1r4pt0r/ittk.
Maybe one more thing. I have written a tool for coloring hexdumps few years ago. The last time I was extracting SMAZ containers, I used it together with ITEPKG, SMEDIA and SMAZ syntax definitions (the same ones that I used to make screenshots for wiki). Here are the links, if you want to give them a try:
I'm not sure if you did it right. In my case (LKV373A-fw/TX\ firmware/LKV373A_TX_20151028_PKG.PKG) it is 0xb70.
I know this is not the best code I've wrote :) I would like to rewrite it from scratch, when I find some time to do that. For now I want to see where the rabbit hole leads me :)
Edit: Ah, one more note. Ignore the errors and other junk printed to stderr. The juice is on stdout, regardless of any errors happening in the meantime.
I skipped the header by this:
but decoding is still failing for me...