Beispiel #1
0
void closeComp(AbstractFile* file) {
    InfoComp* info = (InfoComp*) (file->data);
    uint8_t *compressed;
    if(info->dirty) {
        info->header.checksum = lzadler32((uint8_t*)info->buffer, info->header.length_uncompressed);

        compressed = malloc(info->header.length_uncompressed * 2);
        info->header.length_compressed = (uint32_t)(compress_lzss(compressed, info->header.length_uncompressed * 2, info->buffer, info->header.length_uncompressed) - compressed);

        info->file->seek(info->file, sizeof(info->header));
        info->file->write(info->file, compressed, info->header.length_compressed);

        free(compressed);

        flipCompHeader(&(info->header));
        info->file->seek(info->file, 0);
        info->file->write(info->file, &(info->header), sizeof(info->header));
    }

    free(info->buffer);
    info->file->close(info->file);
    free(info);
    free(file);
}
Beispiel #2
0
int
main(int argc, char **argv)
{
    int rv;
    const char *what;
    const char *filename;
    const char *outname;

    TheImg4 *img4;
    unsigned type;
    unsigned written;
    unsigned char ivkey[16 + 32];
    unsigned char *iv = NULL, *key = NULL;
    unsigned char *output = NULL;
    unsigned outlen = 0;
    int outdup = 0;

    DERItem item;
    unsigned char *data;
    size_t size;

    if (argc < 4) {
        fprintf(stderr, "usage: %s {-image|-extra|-keybag|-ticket} input output [ivkey]\n", argv[0]);
        return 1;
    }

    what = argv[1];
    filename = argv[2];
    outname = argv[3];
    if (argc > 4) {
        rv = str2hex(sizeof(ivkey), ivkey, argv[4]);
        if (rv == sizeof(ivkey)) {
            iv = ivkey;
            key = ivkey + 16;
        }
    }

    data = read_file(filename, 0, &size);
    if (data == NULL) {
        fprintf(stderr, "[e] cannot read '%s'\n", filename);
        return -1;
    }

    img4 = parse(data, size);
    if (!img4) {
        fprintf(stderr, "[e] cannot parse '%s'\n", filename);
        free(data);
        return -1;
    }

    rv = Img4DecodeGetPayloadType(img4, &type);
    if (rv) {
        fprintf(stderr, "[e] cannot identify '%s'\n", filename);
        goto err;
    }
    printf("%c%c%c%c\n", FOURCC(type));

    if (!strncmp(what, "-i", 2) || !strncmp(what, "-e", 2)) {
        int decompress;

        rv = Img4DecodeGetPayload(img4, &item);
        if (rv) {
            fprintf(stderr, "[e] cannot extract payload from '%s'\n", filename);
            goto err;
        }
        output = item.data;
        outlen = item.length;

        if (iv && key) {
            if (outlen & 15) {
                unsigned usize = (outlen + 15) & ~15;
                unsigned char *tmp = calloc(1, usize);
                if (!tmp) {
                    fprintf(stderr, "[e] out of memory %u\n", usize);
                    goto err;
                }
                memcpy(tmp, output, outlen);
                OUTSET(tmp);
            }

            rv = Img4DecodeGetPayloadKeybag(img4, &item);
            if (rv || item.length == 0) {
                fprintf(stderr, "[w] image '%s' has no keybag\n", filename);
            }
#ifdef USE_CORECRYPTO
            cccbc_one_shot(ccaes_cbc_decrypt_mode(), 32, key, iv, (outlen + 15) / 16, output, output);
#else
            AES_KEY decryptKey;
            AES_set_decrypt_key(key, 256, &decryptKey);
            AES_cbc_encrypt(output, output, (outlen + 15) & ~15, &decryptKey, iv, AES_DECRYPT);
#endif
        }

#ifdef iOS10
        if (img4->payload.compression.data && img4->payload.compression.length) {
            DERItem tmp[2];
            uint32_t deco = 0;
            uint64_t usize = 0;
            if (DERParseSequenceContent(&img4->payload.compression, 2, DERImg4PayloadItemSpecs10c, tmp, 0) ||
                DERParseInteger(&tmp[0], &deco) || DERParseInteger64(&tmp[1], &usize)) {
                fprintf(stderr, "[e] cannot get decompression info\n");
                goto err;
            }
            if (deco == 1 && what[1] == 'i') {
                size_t asize = lzfse_decode_scratch_size();
                unsigned char *dec, *aux = malloc(asize);
                if (!aux) {
                    fprintf(stderr, "[e] out of memory %zu\n", asize);
                    goto err;
                }
                dec = malloc(usize + 1);
                if (!dec) {
                    fprintf(stderr, "[e] out of memory %llu\n", usize + 1);
                    free(aux);
                    goto err;
                }
                outlen = lzfse_decode_buffer(dec, usize + 1, output, outlen, aux);
                free(aux);
                if (outlen != usize) {
                    fprintf(stderr, "[e] decompression error\n");
                    free(dec);
                    goto err;
                }
                OUTSET(dec);
            }
        }
#endif
        decompress = (DWORD_BE(output, 0) == 'comp' && DWORD_BE(output, 4) == 'lzss');
        if (decompress && what[1] == 'i') {
            uint32_t csize = DWORD_BE(output, 16);
            uint32_t usize = DWORD_BE(output, 12);
            uint32_t adler = DWORD_BE(output, 8);
            unsigned char *dec = malloc(usize);
            if (outlen > 0x180 + csize) {
                fprintf(stderr, "[i] extra 0x%x bytes after compressed chunk\n", outlen - 0x180 - csize);
            }
            if (!dec) {
                fprintf(stderr, "[e] out of memory %u\n", usize);
                goto err;
            }
            outlen = decompress_lzss(dec, output + 0x180, csize);
            if (adler != lzadler32(dec, outlen)) {
                fprintf(stderr, "[w] adler32 mismatch\n");
            }
            OUTSET(dec);
        } else if (decompress) {
            uint32_t csize = DWORD_BE(output, 16);
            uint32_t usize = outlen - 0x180 - csize;
            if (outlen > 0x180 + csize) {
                unsigned char *dec = malloc(usize);
                if (!dec) {
                    fprintf(stderr, "[e] out of memory %u\n", usize);
                    goto err;
                }
                memcpy(dec, output + 0x180 + csize, usize);
                outlen = usize;
                OUTSET(dec);
            } else {
                OUTSET(NULL);
            }
        } else if (what[1] == 'e') {
            OUTSET(NULL);
        }
        if (!output) {
            fprintf(stderr, "[e] nothing to do\n");
            goto err;
        }
    }
    if (!strncmp(what, "-k", 2)) {
        rv = Img4DecodeGetPayloadKeybag(img4, &item);
        if (rv == 0 && item.length) {
            output = item.data;
            outlen = item.length;
        } else {
            fprintf(stderr, "[e] image '%s' has no keybag\n", filename);
            goto err;
        }
    }
    if (!strncmp(what, "-t", 2)) {
        bool exists = false;
        rv = Img4DecodeManifestExists(img4, &exists);
        if (rv == 0 && exists) {
            output = img4->manifestRaw.data;
            outlen = img4->manifestRaw.length;
        } else {
            fprintf(stderr, "[e] image '%s' has no ticket\n", filename);
            goto err;
        }
    }

    written = write_file(outname, output, outlen);
    if (written != outlen) {
        fprintf(stderr, "[e] cannot write '%s'\n", outname);
        goto err;
    }

    rv = 0;
out:
    if (outdup) {
        free(output);
    }
    free(img4);
    free(data);
    return rv;

err:
    rv = -1;
    goto out;
}