Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const fs = require('fs');
- const path = require('path');
- const zlib = require('zlib');
- const Blowfish = require('egoroof-blowfish');
- const CryptoJS = require('crypto-js');
- // EU
- //const KEY = '83657ea6ffa1e671375c689a2e99a598';
- //const BASE = parseHex('1069d88738c5c75f82b44a1f0a382762');
- // RU
- const KEY = 'a7f33db20dfb711a16d5d3dd3d4cef4d';
- const BASE = parseHex('ee36ace0d87a9eaea565e6884a058b63');
- // KR
- //const KEY = '287f1d85be26e55a1d994e9e1bfd0df1';
- //const BASE = parseHex('6ce3db2fbe338fba87edf2abf6453bfa');
- const outDir = path.resolve(__dirname, 'output2');
- const inFile = 'data2.lpk';
- function parseHex(src) {
- const out = new Uint8Array(src.length / 2);
- for (let i = 0; i < src.length; i += 2) {
- out[i / 2] = parseInt(src.substring(i, i + 2), 16);
- }
- return out;
- }
- const toHex = buf => [...buf].map(v => v.toString(16).padStart(2, '0')).join('');
- function convertEndian(src) {
- for (let i = 0; i + 4 <= src.length; i += 4) {
- const a = src[i], b = src[i + 1], c = src[i + 2], d = src[i + 3];
- src[i] = d; src[i + 1] = c; src[i + 2] = b; src[i + 3] = a;
- }
- return src;
- }
- function fromWords(wordArray) {
- const l = wordArray.sigBytes;
- const words = wordArray.words;
- const result = new Uint8Array(l);
- let i=0 /*dst*/, j=0 /*src*/;
- while (true) {
- // here i is a multiple of 4
- if (i==l) break;
- const w = words[j++];
- result[i++] = (w & 0xff000000) >>> 24;
- if (i === l) break;
- result[i++] = (w & 0x00ff0000) >>> 16;
- if (i === l) break;
- result[i++] = (w & 0x0000ff00) >>> 8;
- if (i==l) break;
- result[i++] = (w & 0x000000ff);
- }
- return result;
- }
- function toWords(buf) {
- return CryptoJS.lib.WordArray.create(buf);
- }
- function toUnicode(str) {
- const res = new Uint8Array(str.length * 2);
- const u16 = new Uint16Array(res.buffer);
- for (let i = 0; i < str.length; ++i) {
- u16[i] = str.charCodeAt(i);
- }
- return res;
- }
- const md5 = buf => fromWords(CryptoJS.MD5(toWords(buf)));
- const sha256 = buf => fromWords(CryptoJS.SHA256(toWords(buf)));
- const aes256 = (buf, pass) => fromWords(CryptoJS.AES.decrypt(toWords(buf), pass));
- const bf = new Blowfish(KEY);
- const decode = data => convertEndian(bf.decode(convertEndian(data), Blowfish.TYPE.UINT8_ARRAY));
- const input = fs.readFileSync(inFile);
- const arrayBuffer = input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
- const u8 = new Uint8Array(arrayBuffer);
- const u32 = new Uint32Array(arrayBuffer);
- const files = u32[0];
- const HDR_SIZE = 528;
- const headers = decode(u8.slice(4, 4 + HDR_SIZE * files));
- const names = [];
- let offset = 8 + HDR_SIZE * files;
- for (let i = 0; i < files; ++i) {
- const buf = headers.slice(i * HDR_SIZE, i * HDR_SIZE + HDR_SIZE);
- const f32 = new Uint32Array(buf.buffer);
- const name = String.fromCharCode(...buf.subarray(4, 4 + f32[0]));
- const dest = path.resolve(outDir, name.slice(1));
- const [uSize, entrySize, zSize] = f32.subarray(f32.length - 3);
- fs.mkdirSync(path.dirname(dest), {recursive: true});
- if (zSize) {
- /*const raw = u8.slice(offset, offset + entrySize);
- try {
- // can't get zlib to uncompress properly, need to play with options (window size etc)
- fs.writeFileSync(dest, zlib.inflateSync(decode(raw).subarray(0, zSize)));
- console.log(dest);
- } catch (e) {
- }*/
- } else {
- const m = name.match(/EFTable_(.*)\.db/);
- if (m) {
- const hash = md5(toUnicode(m[1]));
- const key = new Uint8Array(16);
- for (let i = 0; i < 16; ++i) key[i] = BASE[i] ^ hash[15 - i];
- const key2 = CryptoJS.SHA256(toHex(key));
- const raw = u8.slice(offset, offset + entrySize);
- const dst = new Uint8Array(entrySize);
- const iv = CryptoJS.enc.Hex.parse(''.padStart(64, '0'));
- for (let pos = 0; pos < entrySize; pos += 1024) {
- //dst.set(aes256(raw.subarray(pos, Math.min(pos + 1024, entrySize)), key2), pos);
- const src = raw.subarray(pos, Math.min(pos + 1024, entrySize));
- const d = CryptoJS.AES.decrypt({ciphertext: toWords(src), salt: ''}, key2, {iv});
- dst.set(fromWords(d), pos);
- }
- fs.writeFileSync(dest, dst);
- console.log(dest);
- }
- }
- //console.log(dest);
- offset += entrySize;
- }
Advertisement
Add Comment
Please, Sign In to add comment