decode.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. const beautify = require('js-beautify').js_beautify
  2. const fs = require('fs')
  3. let code = fs.readFileSync('./game.min.js', 'utf8')
  4. // Get dictionary name, stores base64 encoded strings.
  5. let dictName = /^var (\S+)=\[/.exec(code)[1]
  6. // Get the dictionary itself
  7. let dict = JSON.parse(/(\[[^\]]*\])/.exec(code)[1].split("'").join('"')).map(x => Buffer.from(x, 'base64').toString()).map(x => JSON.stringify(x))
  8. // Find the offset for the dictionary
  9. let offset = parseInt(new RegExp(`\\(${dictName},0x([^\\)]*)\\)`).exec(code)[1], 16)
  10. // Find the dictionary function name
  11. let func = new RegExp(`\\(${dictName},0x${offset.toString(16)}\\)\\);var (_0x[^=]*)=`).exec(code)[1]
  12. // Apply the offset
  13. while (--offset >= 0) dict.push(dict.shift())
  14. // Replace strings
  15. code = code.replace(new RegExp(`${func}\\('0x([^']*)'\\)`, 'g'), (_, id) => dict[parseInt(id, 16)])
  16. // Replace x["simpleName"] with x.simpleName
  17. code = code.replace(/\["([a-zA-Z0-9_-]*)"\]/g, (_, x) => `.${x} `)
  18. // Find reverse string function (keep in mine, properties have trailing spaces at this point)
  19. reverseFunc = /(_0x[^\.]+\.\S+) =function\(_0x[^\)]+\){return _0x[^\)]+\.split \(''\)\.reverse \(\)\.join \(''\);}/.exec(code)[1]
  20. // Replace blah.reverse ("gnirtSemos") with "someString"
  21. code = code.replace(new RegExp(`${reverseFunc} \\(("[^"]*")\\)`, 'g'), (_, x) => JSON.stringify(JSON.parse(x).split('').reverse().join('')))
  22. // Replace x["simpleName"] with x.simpleName
  23. code = code.replace(/\["([a-zA-Z0-9_-]*)"\]/g, (_, x) => `.${x} `)
  24. // Replace hex with int
  25. code = code.replace(/([^_])0x([a-f0-9]+)([^"])/g, (_, a, b, c) => `${a}${parseInt(b, 16)}${c}`)
  26. // label Menu class
  27. code = code.split(/this.menu =new (_0x[0-9a-f]*)/.exec(code)[1]).join('Menu')
  28. // label Net class
  29. code = code.split(/this.net =new (_0x[0-9a-f]*)/.exec(code)[1]).join('Net')
  30. // label Game class
  31. code = code.split(/case "game":this.game =new (_0x[0-9a-f]*)/.exec(code)[1]).join('Game')
  32. // label Lobby class
  33. code = code.split(/case "lobby":this.game =new (_0x[0-9a-f]*)/.exec(code)[1]).join('Lobby')
  34. // label Jail class
  35. code = code.split(/case "jail":this.game =new (_0x[0-9a-f]*)/.exec(code)[1]).join('Jail')
  36. // Beautify code
  37. code = beautify(code, {
  38. indent_size: 2
  39. })
  40. fs.writeFileSync('game.decoded.js', code)