App Header
CCDL (32Bytes) |
Import Table (32Bytes) |
Import String (8Bytes) |
Export Table (32Bytes) |
Export String (8Bytes) |
Raw Table (32Bytes) |
Raw Binary |
main.c
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> typedef struct { char ident[4]; uint8_t unknown[20]; uint8_t padding[8]; } __attribute__((__packed__)) _app_ccdl; typedef struct { char ident[4]; uint32_t unknown; uint32_t offset; uint32_t size; uint8_t padding[16]; } __attribute__((__packed__)) _app_impt; typedef struct { char ident[4]; uint32_t unknown; uint32_t offset; uint32_t size; uint8_t padding[16]; } __attribute__((__packed__)) _app_expt; typedef struct { char ident[4]; uint32_t unknown0; uint32_t offset; uint32_t size; uint32_t unknown1; uint32_t entry; uint32_t origin; uint32_t prog_size; } __attribute__((__packed__)) _app_rawd; typedef struct { uint32_t str_offset; uint32_t unknown[2]; uint32_t offset; } __attribute__((__packed__)) _app_impt_entry; typedef struct { uint32_t str_offset; uint32_t unknown[2]; uint32_t offset; } __attribute__((__packed__)) _app_expt_entry; uint32_t print_table(uint8_t *src, uint32_t off, uint32_t size) { uint8_t *p = src + off; uint32_t str_off = off; uint32_t cnt, total = size / sizeof(_app_impt_entry); for (cnt = 0; cnt < total; cnt++) { if (((_app_impt_entry *)p)->unknown[1] > 0x20000) { printf(" string: count(0x%x) offset(0x%x)\n", cnt, str_off); break; } p += sizeof(_app_impt_entry); str_off += sizeof(_app_impt_entry); } p = src + off; for (cnt = 0; cnt < total; cnt++, p += sizeof(_app_impt_entry)) { if (((_app_impt_entry *)p)->unknown[1] == 0x00000) { continue; } if (((_app_impt_entry *)p)->unknown[1] > 0x20000) { break; } printf(" 0x%x(%s)\n", ((_app_impt_entry *)p)->offset, &src[((_app_impt_entry *)p)->str_offset + str_off]); } return str_off; } int main(int argc, char** argv) { if (argc != 2) { printf("Usage:\n app2bin xxx.app\n"); return -1; } FILE* file = fopen(argv[1], "rb"); if (file == NULL) { printf("Failed to open app: %s\n", argv[1]); return -1; } fseek(file, 0, SEEK_END); uintptr_t len = ftell(file); printf("App length: %d\n", len); fseek(file, 0, SEEK_SET); uint8_t* body = (uint8_t *)malloc(len); if (body == NULL) { printf("Failed to allocate buffer for reading app\n"); fclose(file); return -1; } fread(body, 1, len, file); fclose(file); printf("Parsing App...\n"); _app_ccdl ccdl; _app_impt impt; _app_expt expt; _app_rawd rawd; uint8_t *ptr = body; if (memcmp(ptr, "CCDL", 4) != 0) { printf("Invalid App format (miss CCDL section)\n"); goto err; } ptr += sizeof(_app_ccdl); uint32_t cnt = 0, total = 0; uint32_t off = ((_app_impt *)ptr)->offset; uint32_t size = ((_app_impt *)ptr)->size; if (memcmp(ptr, "IMPT", 4) != 0) { printf("Invalid App format (miss IMPT section)\n"); goto err; } printf("Import offset: 0x%x\n", off); printf("Import size: 0x%x\n", size); print_table(body, off, size); ptr += sizeof(_app_impt); if (memcmp(ptr, "EXPT", 4) != 0) { printf("Invalid App format (miss EXPT section)\n"); goto err; } off = ((_app_rawd *)ptr)->offset; size = ((_app_rawd *)ptr)->size; printf("Export offset: %d\n", off); printf("Export size: %d\n", size); print_table(body, off, size); ptr += sizeof(_app_expt); if (memcmp(ptr, "RAWD", 4) != 0) { printf("Invalid App file format (miss RAWD section)\n"); goto err; } off = ((_app_rawd *)ptr)->offset; size = ((_app_rawd *)ptr)->size; printf("Raw offset: %d\n", off); printf("Raw size: %d\n", size); printf("Raw entry: 0x%x\n", ((_app_rawd *)ptr)->entry); printf("Raw origin: 0x%x\n", ((_app_rawd *)ptr)->origin); printf("Raw prog_size: %d\n", ((_app_rawd *)ptr)->prog_size); ptr += sizeof(_app_rawd); unlink("raw.bin"); int fd = open("raw.bin", O_CREAT | O_WRONLY, S_IRUSR); if (fd < 0) { printf("Failed to create raw.bin file\n"); goto err; } write(fd, body + off, size); close(fd); err: free(body); return 0; }
$ sha1sum 7days.app 33e5a1b7eb4a9329a1f5afea6714759e93c6e115 $ ./app2bin 7days.app App length: 45732749 Parsing App... Import offset: 0xa0 Import size: 0x860 string: count(0x48) offset(0x520) 0x80ad4500(abort) 0x80ad4508(printf) 0x80ad4510(sprintf) 0x80ad4518(fprintf) 0x80ad4520(strncasecmp) 0x80ad4528(malloc) 0x80ad4530(realloc) 0x80ad4538(free) 0x80ad4540(fread) 0x80ad4548(fwrite) 0x80ad4550(fseek) 0x80ad4558(LcdGetDisMode) 0x80ad4560(vxGoHome) 0x80ad4568(StartSwTimer) 0x80ad4570(free_irq) 0x80ad4578(fsys_RefreshCache) 0x80ad4580(strlen) 0x80ad4588(_lcd_set_frame) 0x80ad4590(_lcd_get_frame) 0x80ad4598(lcd_get_cframe) 0x80ad45a0(ap_lcd_set_frame) 0x80ad45a8(lcd_flip) 0x80ad45b0(__icache_invalidate_all) 0x80ad45b8(__dcache_writeback_all) 0x80ad45c0(TaskMediaFunStop) 0x80ad45c8(OSCPUSaveSR) 0x80ad45d0(OSCPURestoreSR) 0x80ad45d8(serial_getc) 0x80ad45e0(serial_putc) 0x80ad45e8(_kbd_get_status) 0x80ad45f0(get_game_vol) 0x80ad45f8(_kbd_get_key) 0x80ad4600(fsys_fopen) 0x80ad4608(fsys_fread) 0x80ad4610(fsys_fclose) 0x80ad4618(fsys_fseek) 0x80ad4620(fsys_ftell) 0x80ad4628(fsys_remove) 0x80ad4630(fsys_rename) 0x80ad4638(fsys_ferror) 0x80ad4640(fsys_feof) 0x80ad4648(fsys_fwrite) 0x80ad4650(fsys_findfirst) 0x80ad4658(fsys_findnext) 0x80ad4660(fsys_findclose) 0x80ad4668(fsys_flush_cache) 0x80ad4670(USB_Connect) 0x80ad4678(udc_attached) 0x80ad4680(USB_No_Connect) 0x80ad4688(waveout_open) 0x80ad4690(waveout_close) 0x80ad4698(waveout_close_at_once) 0x80ad46a0(waveout_set_volume) 0x80ad46a8(HP_Mute_sw) 0x80ad46b0(waveout_can_write) 0x80ad46b8(waveout_write) 0x80ad46c0(pcm_can_write) 0x80ad46c8(pcm_ioctl) 0x80ad46d0(OSTimeGet) 0x80ad46d8(OSTimeDly) 0x80ad46e0(OSSemPend) 0x80ad46e8(OSSemPost) 0x80ad46f0(OSSemCreate) 0x80ad46f8(OSTaskCreate) 0x80ad4700(OSSemDel) 0x80ad4708(OSTaskDel) 0x80ad4710(GetTickCount) 0x80ad4718(_sys_judge_event) 0x80ad4720(fsys_fopenW) 0x80ad4728(__to_unicode_le) 0x80ad4730(__to_locale_ansi) Export offset: 2304 Export size: 64 string: count(0x3) offset(0x930) 0x80ad4824(getext) 0x80ad483c(AppMain) Raw offset: 2368 Raw size: 1273280 Raw entry: 0x80ad4740 Raw origin: 0x80a00000 Raw prog_size: 1315408