Last active
December 27, 2019 10:43
-
-
Save SciresM/b96690b6d655f5a925cdb3f91651e887 to your computer and use it in GitHub Desktop.
Quick and dirty NX bootloader uncompression code for 6.2.0+
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <stdbool.h> | |
typedef uint32_t u32; | |
typedef uint8_t u8; | |
typedef struct { | |
u8 *dst; | |
size_t dst_size; | |
size_t dst_off; | |
u8 *src; | |
size_t src_size; | |
size_t src_off; | |
} ctx_t; | |
u8 get_src_byte(ctx_t *ctx) { | |
return ctx->src[ctx->src_off++]; | |
} | |
size_t get_copy_size(ctx_t *ctx, u8 ctrl) { | |
if (ctrl < 0xF) { | |
return ctrl; | |
} | |
size_t sz = ctrl; | |
do { | |
ctrl = get_src_byte(ctx); | |
sz += ctrl; | |
} while (ctrl >= 0xFF); | |
return sz; | |
} | |
size_t uncompress_impl(ctx_t *ctx) { | |
while (true) { | |
u8 ctrl_byte = get_src_byte(ctx); | |
size_t copy_size = get_copy_size(ctx, ctrl_byte >> 4); | |
memcpy(ctx->dst + ctx->dst_off, ctx->src + ctx->src_off, copy_size); | |
ctx->dst_off += copy_size; | |
ctx->src_off += copy_size; | |
if (ctx->src_off >= ctx->src_size) { | |
break; | |
} | |
int wide_ctrl = get_src_byte(ctx); | |
wide_ctrl |= (get_src_byte(ctx) << 8); | |
size_t wide_copy_size = get_copy_size(ctx, ctrl_byte & 0xF); | |
size_t end_off = ctx->dst_off + wide_copy_size + 4; | |
for (size_t cur_off = ctx->dst_off; cur_off < end_off; ctx->dst_off = cur_off) { | |
if (wide_ctrl >= cur_off) { | |
printf("OOB ACCESS!\n"); | |
while (true) { | |
} | |
} | |
ctx->dst[cur_off] = ctx->dst[cur_off - wide_ctrl]; | |
cur_off++; | |
} | |
} | |
} | |
size_t uncompress(void *input, size_t input_size, void *output, size_t output_size) { | |
ctx_t ctx; | |
ctx.src = (u8 *)input; | |
ctx.src_size = input_size; | |
ctx.src_off = 0; | |
ctx.dst = (u8 *)output; | |
ctx.dst_size = output_size; | |
ctx.dst_off = 0; | |
return uncompress_impl(&ctx); | |
} | |
int main(int argc, char **argv) { | |
if (argc != 2) { | |
fprintf(stderr, "Usage: %s input\n", argv[0]); | |
return EXIT_FAILURE; | |
} | |
size_t inp_size = 0; | |
size_t out_size = 0x1C000; | |
void *output = calloc(1, out_size); | |
FILE *fp = fopen(argv[1], "rb"); | |
fseek(fp, 0L, SEEK_END); | |
inp_size = ftell(fp); | |
fseek(fp, 0L, SEEK_SET); | |
void *input = calloc(1, inp_size); | |
fread(input, inp_size, 1, fp); | |
fclose(fp); | |
printf("Decompressing...\n"); | |
printf("Out: %08x\n", uncompress(input, inp_size, output, out_size)); | |
fp = fopen("output.bin", "wb"); | |
fwrite(output, out_size, 1, fp); | |
fclose(fp); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment