Advertisement
Guest User

Untitled

a guest
Feb 12th, 2017
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.51 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/stat.h>
  5. #include <zlib.h>
  6.  
  7. #include "tldat.h"
  8.  
  9. static const uint64_t KEYS[] =
  10. {
  11.     0x551b8a2ecd6197efLL,
  12.     0x186a57f394700e34LL,
  13.     0x3e9f2e302712b938LL,
  14.     0xe14c2303ccc551f2LL,
  15.     0xccf38ca1f5c17133LL,
  16.     0x2353622f23b1c9dbLL,
  17.     0x34afadac84ae7417LL,
  18.     0xa5dcaca1d9365ebLL,
  19.     0xf262becf99cd3c0fLL,
  20.     0x3125b4b2f481962LL,
  21.     0xcd5ec4039782a7aaLL,
  22.     0x7e33b2fc317e77f3LL,
  23.     0xbefb5409bb40d4faLL,
  24.     0x3368c49e410e24efLL,
  25.     0x1e9693617e3e6bbfLL,
  26.     0x9c35278e358912b1LL
  27. };
  28.  
  29. static void tldecrypt(uint64_t key, uint8_t *data, uint64_t size)
  30. {
  31.     uint64_t tmp, t;
  32.     unsigned i;
  33.    
  34.     for (i = 0; i < ((size / 16) * 16); i += 8)
  35.     {
  36.         *(uint64_t *)(data + i) ^= key;
  37.         tmp = key ^ 0x4e3362bf7a4c7c26LL;
  38.         tmp ^= tmp << 13;
  39.         tmp ^= tmp >> 7;
  40.         t = ((int)(data[i + 7]) << ((((i - 1) & 7) << 3)) % 32) |
  41.             ((int)(data[i + 4]) << ((((i - 4) & 7) << 3)) % 32) |
  42.             ((int)(data[i + 1]) << ((((i + 1) & 7) << 3)) % 32) |
  43.             ((int)(data[i + 5]) << ((((i - 3) & 7) << 3)) % 32) |
  44.             ((int)(data[i]) << (((i & 7) << 3)) % 32) |
  45.             ((int)(data[i + 2]) << ((((i + 2) & 7) << 3)) % 32) |
  46.             ((int)(data[i + 6]) << ((((i - 2) & 7) << 3)) % 32) |
  47.             ((int)(data[i + 3]) << ((((i + 3) & 7) << 3)) % 32);
  48.         key = tmp ^ (tmp << 17) ^ t;
  49.     }
  50.    
  51.     for (; i < size; i++)
  52.         data[i] ^= key >> ((i & 7) << 3);
  53. }
  54.  
  55. tldat_t * tldat_init(const char *path)
  56. {
  57.     struct stat st;
  58.     FILE *hda = NULL, *hdb = NULL;
  59.     tldat_t *tldat = NULL;
  60.    
  61.     if (tldat = (tldat_t *)malloc(sizeof(tldat_t)))
  62.     {
  63.         memset(tldat, 0, sizeof(tldat_t));
  64.         tldat->path = (char *)calloc(strlen(path)+1, sizeof(char));
  65.         strcpy(tldat->path, path);
  66.     }
  67.     else
  68.         return NULL;
  69.    
  70.     char *hdapath = NULL, *hdbpath = NULL;
  71.     if (stat(path, &st) == 0)
  72.     {
  73.         if (!S_ISDIR(st.st_mode))
  74.         {
  75.             tldat->err = ERR_INV_PATH;
  76.             return tldat;
  77.         }
  78.        
  79.         hdapath = (char *)calloc(strlen(path)+24, sizeof(char));
  80.         strcpy(hdapath, path);
  81.         strcat(hdapath, "/FILEHEADER.TOFHDA");
  82.         hdbpath = (char *)calloc(strlen(path)+24, sizeof(char));
  83.         strcpy(hdbpath, path);
  84.         strcat(hdbpath, "/FILEHEADER.TOFHDB");
  85.     }
  86.     else
  87.     {
  88.         tldat->err = ERR_INV_PATH;
  89.         return tldat;
  90.     }
  91.    
  92.     uint64_t *hda_keys = NULL;
  93.     if (hda = fopen(hdapath, "rb"))
  94.     {
  95.         stat(hdapath, &st);
  96.         hda_keys = (uint64_t *)calloc(st.st_size/8, sizeof(uint64_t));
  97.         fread(hda_keys, 8, st.st_size/8, hda);
  98.         fclose(hda);
  99.         free(hdapath);
  100.     }
  101.     else
  102.     {
  103.         tldat->err = ERR_FNF_HDA;
  104.         free(hdapath);
  105.         return tldat;
  106.     }
  107.    
  108.     uint64_t key1 = hda_keys[12] & 15;
  109.     uint64_t key2 = (hda_keys[4] >> 4) & 15;
  110.     free(hda_keys);
  111.     if (key1 == key2) key2 = (key2 + 1) & 15;
  112.     key1 = KEYS[key1];
  113.     key2 = KEYS[key2];
  114.     key1 ^= key2;
  115.    
  116.     uint8_t * hdb_buf = NULL;
  117.     if (hdb = fopen(hdbpath, "rb"))
  118.     {
  119.         stat(hdbpath, &st);
  120.         hdb_buf = (uint8_t *)malloc(st.st_size);
  121.         fread(hdb_buf, 1, st.st_size, hdb);
  122.         tldecrypt(key1, hdb_buf, st.st_size);
  123.         fclose(hdb);
  124.         free(hdbpath);
  125.     }
  126.     else
  127.     {
  128.         tldat->err = ERR_FNF_HDB;
  129.         free(hdbpath);
  130.         return tldat;
  131.     }
  132.    
  133.     memmove(&tldat->entries_offs, &hdb_buf[8], 8); // first 8 bytes are padding
  134.     memmove(&tldat->nentries, &hdb_buf[16], 8);
  135.     memmove(&tldat->info_offs, &hdb_buf[40], 8); // 16 bytes of padding
  136.     memmove(&tldat->nfiles, &hdb_buf[48], 8);
  137.    
  138.     uint8_t *pos = &hdb_buf[tldat->entries_offs];
  139.     tldat->crcs = (uint32_t *)calloc(tldat->nfiles, sizeof(uint32_t));
  140.     tldat->keys = (uint32_t *)calloc(tldat->nfiles, sizeof(uint32_t));
  141.     tldat->recs = (tldat_rec_t *)calloc(tldat->nfiles, sizeof(tldat_rec_t));
  142.     for (uint64_t i = 0; i < tldat->nfiles; i++)
  143.     {
  144.         tldat->crcs[i] = *(uint32_t *)pos;
  145.         pos += 4;
  146.         tldat->keys[i] = *(uint32_t *)pos;
  147.         pos += 4;
  148.     }
  149.    
  150.     for (uint64_t i = 0; i < tldat->nfiles; i++)
  151.     {
  152.         memmove(&tldat->recs[i], &hdb_buf[tldat->info_offs], sizeof(tldat_rec_t) - sizeof(uint64_t));
  153.        
  154.         for (uint64_t x = 0; x < tldat->nentries; x++)
  155.             if (tldat->crcs[x] == tldat->recs[i].crc)
  156.             {
  157.                 tldat->recs[i].key = tldat->keys[x];
  158.                 break;
  159.             }
  160.            
  161.         tldat->recs[i].key = ((3 - (tldat->recs[i].key & 3)) << 2) |
  162.             (tldat->recs[i].key & 0xfffffffffffffff0LL) |
  163.             ((tldat->recs[i].key >> 2) & 3);
  164.     }
  165.    
  166.     free(hdb_buf);
  167.     return tldat;
  168. }
  169.  
  170. int tldat_extract(tldat_t *tldat, uint64_t idx, const char *outpath)
  171. {
  172.     struct stat st;
  173.     if (stat(outpath, &st) == 0)
  174.         if (!S_ISDIR(st.st_mode))
  175.         {
  176.             tldat->err = ERR_INV_OUTDIR;
  177.             return tldat->err;
  178.         }
  179.     else
  180.     {
  181.         tldat->err = ERR_INV_OUTDIR;
  182.         return tldat->err;
  183.     }
  184.    
  185.     uint8_t *buf = (uint8_t *)calloc(tldat->recs[idx].zsize, sizeof(char));
  186.     FILE *dat = NULL, *outfile = NULL;
  187.     char *datpath = (char *)calloc(strlen(tldat->path)+32, sizeof(char));
  188.     strcpy(datpath, tldat->path);
  189.     strcat(datpath, "/TLFILE.TLDAT");
  190.     if (dat = fopen(datpath, "rb"))
  191.     {
  192.         fseek(dat, tldat->recs[idx].offs, SEEK_SET);
  193.         fread(buf, 1, tldat->recs[idx].zsize, dat);
  194.         fclose(dat);
  195.         tldecrypt(tldat->recs[idx].key, buf, tldat->recs[idx].zsize);
  196.        
  197.         char *outfilepath = (char *)calloc(strlen(outpath)+10, sizeof(char));
  198.         strcpy(outfilepath, outpath);
  199.         strcat(outfilepath, "/");
  200.         if (tldat->recs[idx].size == tldat->recs[idx].zsize) // uncompressed?
  201.         {
  202.             strncat(outfilepath, tldat->recs[idx].type, 8);
  203.             if (outfile = fopen(outfilepath, "wb+x"))
  204.             {
  205.                 fwrite(buf, 1, tldat->recs[idx].zsize, outfile);
  206.                 fclose(outfile);
  207.             }
  208.             else
  209.                 tldat->err = ERR_WRITE;
  210.         }
  211.         else
  212.         {
  213.             uint32_t tlzc;
  214.             memmove(&tlzc, buf, 4);
  215.            
  216.             if (tlzc == 0x435a4c54) // 'TLZC'
  217.             {
  218.                 uint32_t tver, tzsize, tsize;
  219.                 memmove(&tver, &buf[4], 4);
  220.                 memmove(&tzsize, &buf[8], 4);
  221.                 memmove(&tsize, &buf[12], 4);
  222.                
  223.                 if (tver == 0x201) // Abyss
  224.                 {
  225.                     char dummy[8];
  226.                     z_stream zs;
  227.                    
  228.                     memmove(dummy, &buf[16], 8);
  229.                     memset(&zs, 0, sizeof(z_stream));
  230.                     tzsize -= 24;
  231.                     if ((tldat->err = inflateInit(&zs)) == NO_ERROR)
  232.                     {
  233.                         uint8_t *inbuf = (uint8_t *)calloc(tzsize, sizeof(char));
  234.                         uint8_t *outbuf = (uint8_t *)calloc(tsize, sizeof(char));
  235.                        
  236.                         memmove(inbuf, &buf[24], tzsize);
  237.                         zs.avail_in = tzsize;
  238.                         zs.next_in = inbuf;
  239.                         zs.avail_out = tsize;
  240.                         zs.next_out = outbuf;
  241.                         if ((tldat->err = inflate(&zs, Z_NO_FLUSH)) == Z_STREAM_END)
  242.                         {
  243.                             strncat(outfilepath, dummy, 8);
  244.                             if (outfile = fopen(outfilepath, "wb+x"))
  245.                             {
  246.                                 fwrite(outbuf, 1, tsize, outfile);
  247.                                 fclose(outfile);
  248.                             }
  249.                             else
  250.                                 tldat->err = ERR_WRITE;
  251.                         }
  252.                        
  253.                         inflateEnd(&zs);
  254.                         free(inbuf);
  255.                         free(outbuf);
  256.                     }
  257.                 }
  258.                 else if (tver == 0x401) // Symphonia, unsupported, unknown lzma and encryption
  259.                 {
  260.                     char dummy[8];
  261.                    
  262.                     memmove(dummy, &buf[16], 8);
  263.                     tzsize -= 24;
  264.                    
  265.                     strncat(outfilepath, dummy, 8);
  266.                     if (outfile = fopen(outfilepath, "wb+x"))
  267.                     {
  268.                         fwrite(buf, 1, tldat->recs[idx].zsize, outfile);
  269.                         fclose(outfile);
  270.                     }
  271.                     else
  272.                         tldat->err = ERR_WRITE;
  273.                 }
  274.                 else
  275.                 {
  276.                     char dummy[9];
  277.                     uint32_t chunk_size, nchunks;
  278.                 }
  279.             }
  280.             else
  281.             {
  282.                 strcat(outfilepath, "unsupported-");
  283.                 strncat(outfilepath, tldat->recs[idx].type, 8);
  284.                 if (outfile = fopen(outfilepath, "wb+x"))
  285.                 {
  286.                     fwrite(buf, 1, tldat->recs[idx].size, outfile);
  287.                     fclose(outfile);
  288.                 }
  289.                 else
  290.                     tldat->err = ERR_WRITE;
  291.             }
  292.         }
  293.        
  294.         free(outfilepath);
  295.         free(buf);
  296.     }
  297.     else
  298.         tldat->err = ERR_FNF_TLDAT;
  299.     free(datpath);
  300. }
  301.  
  302. void tldat_free(tldat_t *tldat)
  303. {
  304.     if (tldat)
  305.     {
  306.         free(tldat->crcs);
  307.         free(tldat->keys);
  308.         free(tldat->recs);
  309.         free(tldat->path);
  310.         free(tldat);
  311.     }
  312. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement