-
-
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...