Advertisement
Guest User

Untitled

a guest
Sep 25th, 2023
428
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const fs = require('fs');
  2. const path = require('path');
  3. const zlib = require('zlib');
  4. const Blowfish = require('egoroof-blowfish');
  5. const CryptoJS = require('crypto-js');
  6.  
  7. // EU
  8. //const KEY = '83657ea6ffa1e671375c689a2e99a598';
  9. //const BASE = parseHex('1069d88738c5c75f82b44a1f0a382762');
  10. // RU
  11. const KEY = 'a7f33db20dfb711a16d5d3dd3d4cef4d';
  12. const BASE = parseHex('ee36ace0d87a9eaea565e6884a058b63');
  13. // KR
  14. //const KEY = '287f1d85be26e55a1d994e9e1bfd0df1';
  15. //const BASE = parseHex('6ce3db2fbe338fba87edf2abf6453bfa');
  16.  
  17. const outDir = path.resolve(__dirname, 'output2');
  18. const inFile = 'data2.lpk';
  19.  
  20. function parseHex(src) {
  21.   const out = new Uint8Array(src.length / 2);
  22.   for (let i = 0; i < src.length; i += 2) {
  23.     out[i / 2] = parseInt(src.substring(i, i + 2), 16);
  24.   }
  25.   return out;
  26. }
  27. const toHex = buf => [...buf].map(v => v.toString(16).padStart(2, '0')).join('');
  28. function convertEndian(src) {
  29.   for (let i = 0; i + 4 <= src.length; i += 4) {
  30.     const a = src[i], b = src[i + 1], c = src[i + 2], d = src[i + 3];
  31.     src[i] = d; src[i + 1] = c; src[i + 2] = b; src[i + 3] = a;
  32.   }
  33.   return src;
  34. }
  35. function fromWords(wordArray) {
  36.   const l = wordArray.sigBytes;
  37.   const words = wordArray.words;
  38.   const result = new Uint8Array(l);
  39.   let i=0 /*dst*/, j=0 /*src*/;
  40.   while (true) {
  41.     // here i is a multiple of 4
  42.     if (i==l) break;
  43.     const w = words[j++];
  44.     result[i++] = (w & 0xff000000) >>> 24;
  45.     if (i === l) break;
  46.     result[i++] = (w & 0x00ff0000) >>> 16;
  47.     if (i === l) break;
  48.     result[i++] = (w & 0x0000ff00) >>> 8;
  49.     if (i==l) break;
  50.     result[i++] = (w & 0x000000ff);
  51.   }
  52.   return result;
  53. }
  54. function toWords(buf) {
  55.   return CryptoJS.lib.WordArray.create(buf);
  56. }
  57. function toUnicode(str) {
  58.   const res = new Uint8Array(str.length * 2);
  59.   const u16 = new Uint16Array(res.buffer);
  60.   for (let i = 0; i < str.length; ++i) {
  61.     u16[i] = str.charCodeAt(i);
  62.   }
  63.   return res;
  64. }
  65.  
  66. const md5 = buf => fromWords(CryptoJS.MD5(toWords(buf)));
  67. const sha256 = buf => fromWords(CryptoJS.SHA256(toWords(buf)));
  68. const aes256 = (buf, pass) => fromWords(CryptoJS.AES.decrypt(toWords(buf), pass));
  69.  
  70. const bf = new Blowfish(KEY);
  71. const decode = data => convertEndian(bf.decode(convertEndian(data), Blowfish.TYPE.UINT8_ARRAY));
  72.  
  73. const input = fs.readFileSync(inFile);
  74. const arrayBuffer = input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
  75.  
  76. const u8 = new Uint8Array(arrayBuffer);
  77. const u32 = new Uint32Array(arrayBuffer);
  78.  
  79. const files = u32[0];
  80.  
  81. const HDR_SIZE = 528;
  82.  
  83. const headers = decode(u8.slice(4, 4 + HDR_SIZE * files));
  84.  
  85. const names = [];
  86.  
  87. let offset = 8 + HDR_SIZE * files;
  88. for (let i = 0; i < files; ++i) {
  89.   const buf = headers.slice(i * HDR_SIZE, i * HDR_SIZE + HDR_SIZE);
  90.   const f32 = new Uint32Array(buf.buffer);
  91.   const name = String.fromCharCode(...buf.subarray(4, 4 + f32[0]));
  92.   const dest = path.resolve(outDir, name.slice(1));
  93.   const [uSize, entrySize, zSize] = f32.subarray(f32.length - 3);
  94.   fs.mkdirSync(path.dirname(dest), {recursive: true});
  95.   if (zSize) {
  96.     /*const raw = u8.slice(offset, offset + entrySize);
  97.     try {
  98.       // can't get zlib to uncompress properly, need to play with options (window size etc)
  99.       fs.writeFileSync(dest, zlib.inflateSync(decode(raw).subarray(0, zSize)));
  100.       console.log(dest);
  101.     } catch (e) {
  102.     }*/
  103.   } else {
  104.     const m = name.match(/EFTable_(.*)\.db/);
  105.     if (m) {
  106.       const hash = md5(toUnicode(m[1]));
  107.       const key = new Uint8Array(16);
  108.       for (let i = 0; i < 16; ++i) key[i] = BASE[i] ^ hash[15 - i];
  109.       const key2 = CryptoJS.SHA256(toHex(key));
  110.       const raw = u8.slice(offset, offset + entrySize);
  111.       const dst = new Uint8Array(entrySize);
  112.       const iv = CryptoJS.enc.Hex.parse(''.padStart(64, '0'));
  113.       for (let pos = 0; pos < entrySize; pos += 1024) {
  114.         //dst.set(aes256(raw.subarray(pos, Math.min(pos + 1024, entrySize)), key2), pos);
  115.         const src = raw.subarray(pos, Math.min(pos + 1024, entrySize));
  116.         const d = CryptoJS.AES.decrypt({ciphertext: toWords(src), salt: ''}, key2, {iv});
  117.         dst.set(fromWords(d), pos);
  118.       }
  119.       fs.writeFileSync(dest, dst);
  120.       console.log(dest);      
  121.     }
  122.   }
  123.   //console.log(dest);
  124.   offset += entrySize;
  125. }
  126.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement