rendered paste body#include <stdio.h>#include <stdlib.h>#include <string.h>//#include <direct.h>#include <signal.h>#include <errno.h>struct pak_header_data{ unsigned char magic[4]; unsigned short flags; unsigned short unknown1; unsigned int block_sz; unsigned int num_entries;};struct pak_entry_data{ unsigned int flags; int startsector; // byte offset = startsector * 2048 int filesize; char ident[4]; unsigned int unknown2; unsigned int crc; int unknown4; int unknown5; unsigned char namelen; unsigned char filepath[255];};unsigned char *p_tab1;unsigned char *p_tab2;static unsigned char init_parm[4] = { 0x36, 0x05, 0xbf, 0xce };unsigned char tab1[] = { 0xf8, 0x96, 0x54, 0x41, 0xc7, 0x04, 0xb8, 0x41, 0x7c, 0x5d, 0xbe, 0x07, 0x6b, 0x62, 0x54, 0xc1,};unsigned char tab2[] = { 0x15, 0xa0, 0x38, 0x25, 0x35, 0x1c, 0xad, 0x5b, 0x6d, 0x52, 0x7a, 0x36, 0xa8, 0x17, 0x1d, 0x20,};static struct _codec_parm{ unsigned int seed; unsigned int variable;} codec_parm;unsigned intget_u32_be (unsigned char *p){ unsigned int ret = 0; if (p) { ret |= p[3]; ret |= p[2] << 8; ret |= p[1] << 16; ret |= p[0] << 24; } return ret;}unsigned intget_u32_le (unsigned char *p){ return *(unsigned int *) p;}unsigned int (*get_u32) (unsigned char *p);#define SZ_KEYS (sizeof(tab1)/sizeof(unsigned int))unsigned intCal_KEY (unsigned int s_1, unsigned int s_2){ unsigned char i = 0; for (; i < SZ_KEYS; i++) { unsigned int lo, hi, temp, seed = s_2; temp = seed ^ get_u32 (p_tab1 + (i * 4)); hi = ((temp >> 16) & 0xffff); lo = ((temp) & 0xffff); temp = (lo * lo) + ~(hi * hi); temp = (temp << 16) | (temp >> 16); s_2 = temp ^ get_u32 (p_tab2 + (i * 4)); s_2 += lo * hi; s_2 ^= s_1; s_1 = seed; } return s_2;}voidcodec (unsigned char *buff, unsigned int size, struct _codec_parm *p_parm){ unsigned char *p_buff = buff; unsigned int res, offset = 0; unsigned char key[4]; struct _codec_parm temp; temp.seed = ~(p_parm->seed - 1); temp.variable = p_parm->variable; while (size > offset) { if (!(offset & 3)) { res = Cal_KEY (temp.seed, temp.variable); key[3] = res; key[2] = res >>= 1; key[1] = res >>= 1; key[0] = res >>= 1; temp.variable += 1; } *p_buff++ ^= key[offset++ & 3]; }; p_parm->variable = temp.variable;}static unsigned int crc32_table[256];static __inline unsigned intcrc_reflect (unsigned int ref, unsigned int ch){ unsigned int value = 0, i; for (i = 1; i < (ch + 1); i++) { if (ref & 1) value |= 1 << (ch - i); ref >>= 1; } return value;}voidcrc_init (){#define POLY (0x04c11db7) unsigned int value = 0, i, j; for (i = 0; i <= 256 - 1; i++) { crc32_table[i] = crc_reflect (i, 8) << 24; for (j = 0; j < 8; j++) crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (1 << 31) ? POLY : 0); crc32_table[i] = crc_reflect (crc32_table[i], 32); }}static __inline unsigned intget_crc (unsigned char *p, unsigned int len, unsigned int crc){ while (len--) crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ *p++]; return ~crc;}voidendian_init (void){ unsigned short endian = 1; unsigned char *p_e = (unsigned char *) &endian; if (!*p_e) get_u32 = get_u32_be; else get_u32 = get_u32_le;}unsigned charinit (unsigned int variable){ unsigned char t_tab1[] = { 0xbc, 0x1f, 0x46, 0x64, 0x09, 0x99, 0x82, 0x34, 0xc0, 0x25, 0x4f, 0xe5, 0xb7, 0xdb, 0x26, 0x25, }; unsigned char t_tab2[] = { 0x35, 0xe0, 0xb8, 0x25, 0x9d, 0x4d, 0x0e, 0x1d, 0xdc, 0x31, 0xbc, 0xbb, 0x78, 0xb6, 0x5e, 0xa7, }; p_tab1 = t_tab1; p_tab2 = t_tab2; codec_parm.seed = 0x6C69746E; codec_parm.variable = variable; codec ((unsigned char *) init_parm, sizeof (unsigned int), &codec_parm); codec (tab1, sizeof (tab1), &codec_parm); codec (tab2, sizeof (tab2), &codec_parm); p_tab1 = tab1; p_tab2 = tab2; codec_parm.seed = get_u32 (init_parm); codec_parm.variable = 1; if (get_crc (tab1, sizeof (tab1), 0 - 1) != 0x5CBE2D0F || get_crc (tab2, sizeof (tab2), 0 - 1) != 0x7BA1A34F) return 0; else return 1;}#define _UC(p) ((unsigned char *)p)intmain (int argc, char **argv){ FILE *infp, *outfp; struct pak_header_data h; struct pak_entry_data e; char *f_name = "FILES.PAK"; unsigned int i, crc_f = 0; if (argc > 2) { printf ("Usage: codec_pak file.ext\n"); exit (1); } if (argc == 2) f_name = argv[1]; if (!(infp = fopen (f_name, "rb"))) { printf ("Error: cannot open %s : %s\n", f_name, strerror (errno), NULL); exit (1); } fread (&h, sizeof (h), 1, infp); crc_init (); endian_init (); if (!init (get_u32 ((unsigned char *) &h.magic))) goto out; if (h.flags >> 9) { codec ((unsigned char *) &h.unknown1, sizeof (h.unknown1), &codec_parm); codec ((unsigned char *) &h.block_sz, sizeof (h.block_sz), &codec_parm); codec ((unsigned char *) &h.num_entries, sizeof (h.num_entries), &codec_parm); } printf ("HDR: ID:%c%c%c%c, entries:%d\n", h.magic[0], h.magic[1], h.magic[2], h.magic[3], get_u32 (_UC (&h.num_entries))); mkdir ("extracted",0777); chdir ("extracted"); codec_parm.seed = get_u32 (_UC (&h.num_entries)) + (1 << 31); codec_parm.variable = 1;#define entry_start(n) (sizeof(struct pak_header_data) + (sizeof(struct pak_entry_data) * n)) for (i = 0; i < get_u32 (_UC (&h.num_entries)); i++) { static unsigned char temp[4 * 1024]; unsigned int count, sz, crc; struct _codec_parm t_parm; fseek (infp, entry_start (i), SEEK_SET); if (fread (&e, sizeof (struct pak_entry_data), 1, infp) != 1) { printf ("failed reading file: %s\n", strerror (errno)); break; } if (h.flags >> 8) codec ((unsigned char *) &e, sizeof (struct pak_entry_data), &codec_parm); printf ("E:%d: ID:%c%c%c%c, filepath:%s, size:%d, ", i + 1, e.ident[0], e.ident[1], e.ident[2], e.ident[3], e.filepath, get_u32 (_UC (&e.filesize))); { char *p_name = (char *) &e.filepath; int ii = e.namelen - 1; for (; ii > 0; ii--) { if ((p_name[ii] == '/') || (p_name[ii] == '\\')) { int iii; char slash = p_name[ii]; p_name[ii] = '\0'; for (iii = 0; ii > iii; iii++) { if ((p_name[iii] == '/') || (p_name[iii] == '\\')) { p_name[iii] = '\0'; mkdir (e.filepath,0777); p_name[iii] = slash; } } mkdir (e.filepath,0777); p_name[ii] = slash; break; } } } /* * temp = (unsigned char *) calloc(1, get_u32(_UC(&e.filesize))); * fseek(infp, get_u32(_UC(&e.startsector)) * get_u32(_UC(&h.block_sz)), SEEK_SET); * fread(temp, get_u32(_UC(&e.filesize)), 1, infp); * */ fseek (infp, get_u32 (_UC (&e.startsector)) * get_u32 (_UC (&h.block_sz)), SEEK_SET); if (get_u32 (_UC (&e.flags)) >> 31) // coded { t_parm.seed = get_u32 (_UC (&e.filesize)) + get_u32 (_UC (&e.flags)); t_parm.variable = 1; } if (!(outfp = fopen (e.filepath, "wb"))) { printf ("Error: cannot open %s for writing: %s\n", e.filepath, strerror (errno)); continue; } crc = 0 - 1; for (count = get_u32 (_UC (&e.filesize)); count > 0;) { sz = count > get_u32 (_UC (&h.block_sz)) ? get_u32 (_UC (&h.block_sz)) : count; fread (temp, sz, 1, infp); if (get_u32 (_UC (&e.flags)) >> 31) // coded codec ((unsigned char *) temp, sz, &t_parm); crc = ~get_crc (temp, sz, crc); fwrite (temp, sz, 1, outfp); count -= sz; } fclose (outfp); printf ("crc32:"); if (get_u32 (_UC (&e.crc)) == ~crc) printf ("OK\n"); else printf ("%s %0X != %0X\n", (crc_f++, "FAIL"), get_u32 (_UC (&e.crc)), crc); } printf ("Files OK:%d, FAIL:%d\n", h.num_entries - crc_f, crc_f);out: fclose (infp); exit (0);}