0

I try modify project wrote in LUA script. But i dn't know why i can't read it. It looks like encripted. It is possible to read this file ? here is file https://easyupload.io/c3u934

screen from file

i used unluac but i it doesnt work. below is my example:

java -jar unluac.jar options.lua > myfile_decompiled.lua

Exception in thread "main" java.lang.IllegalStateException: The input file does not have the signature of a valid Lua file.
        at unluac.parse.BHeader.<init>(BHeader.java:70)
        at unluac.Main.file_to_function(Main.java:116)
        at unluac.Main.main(Main.java:58)
rrrrcode
  • 13
  • 4

1 Answers1

0

When I looked at the file with a hex editor, I saw a lot of repeating patterns, which implied weak XOR encryption. Long strings of the 0x05 byte really made this seem likely, which I suspected were spaces (0x20) in the original Lua file. I XOR'd every byte of the file with 0x25 to test this theory, and it worked! Here's the result:

EnterGame = { }

-- private variables
local loadBox
local enterGame
local motdWindow
clientBox = nil
local protocolLogin
local motdEnabled = true
local progressWindow
local startTime
-- private functions
local function onError(protocol, message, errorCode)
  if loadBox then
    loadBox:destroy()
    loadBox = nil
  end

  if enterGame:getChildById('rememberPasswordBox'):isChecked() then

        --local account = g_crypt.xorCrypt(G.account, 123)
    --local password = g_crypt.xorCrypt(G.password, 123)

        local account = g_crypt.encrypt(G.account)
    local password = g_crypt.encrypt(G.password)

    if account ~= "" and password ~= "" then
      g_settings.set('account', account)
      g_settings.set('password', password)
      ServerList.setServerAccount(G.host, account)
      ServerList.setServerPassword(G.host, password)
        end
  else
    -- reset server list account/password
    ServerList.setServerAccount(G.host, '')
    ServerList.setServerPassword(G.host, '')
    EnterGame.clearAccountFields()
  end

  local errorBox = displayErrorBox(tr('Login Error'), message)
  connect(errorBox, { onOk = EnterGame.show })
end

local function onMotd(protocol, motd)
  G.motdNumber = tonumber(motd:sub(0, motd:find("\n")))
  G.motdMessage = motd:sub(motd:find("\n") + 1, #motd)
  if motdEnabled then
  end
end

local function onCharacterList(protocol, characters, account, otui)
  -- Try add server to the server list
  ServerList.add(G.host, G.port, g_game.getClientVersion())

  if enterGame:getChildById('rememberPasswordBox'):isChecked() then

    local account = g_crypt.encrypt(G.account)
    local password = g_crypt.encrypt(G.password)

        --local account = g_crypt.xorCrypt(G.account, 123)
    --local password = g_crypt.xorCrypt(G.password, 123)

    if account ~= "" and  password ~= "" then
      g_settings.set('account', account)
      g_settings.set('password', password)
      ServerList.setServerAccount(G.host, account)
      ServerList.setServerPassword(G.host, password)
        end
  else
    -- reset server list account/password
    ServerList.setServerAccount(G.host, '')
    ServerList.setServerPassword(G.host, '')
    EnterGame.clearAccountFields()
  end

  loadBox:destroy()
  loadBox = nil

  CharacterList.create(characters, account, otui)
  CharacterList.show()

  if motdEnabled then
    local lastMotdNumber = g_settings.getNumber("motd")
    if G.motdNumber and G.motdNumber ~= lastMotdNumber then
      g_settings.set("motd", G.motdNumber)
      motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage)
      connect(motdWindow, { onOk = function() CharacterList.show() motdWindow = nil end })
      CharacterList.hide()
    end
  end
end

-- public functions
function EnterGame.init()
  connect(g_app, { onExit = onExitFunc })
  enterGame = g_ui.displayUI('entergame')

  g_keyboard.bindKeyDown('Ctrl+G', EnterGame.openWindow)

  local account = g_settings.get('account')
  local password = g_settings.get('password')
  local host = g_settings.get('host')
  local port = g_settings.get('port')
  local clientVersion = g_settings.getInteger('client-version')
  local proxy = g_settings.get('proxy')
  if clientVersion == 0 then clientVersion = 772 end
  if port == nil or port == 0 then port = 7181 end

  if account ~= "" then
     EnterGame.setAccountName(account)
  end
  if password ~= "" then
     EnterGame.setPassword(password)
  end

  enterGame:getChildById('serverHostTextEdit'):setText(host)
  enterGame:getChildById('serverPortTextEdit'):setText(port)
  clientBox = enterGame:getChildById('clientComboBox')

  clientBox:addOption("Prosperity")
  clientBox:addOption("Encounter")
  clientBox:addOption("Redemption")
  clientBox:addOption("War")
  --clientBox:addOption("test")
  clientBox:setCurrentOption(proxy)
  clientBox.menuHeight = 97
  --clientBox:hide()
  enterGame:hide()

  if g_app.isRunning() and not g_game.isOnline() then
    enterGame:show()
  end
end

function EnterGame.terminate()
  disconnect(g_app, { onExit = onExitFunc })

  g_keyboard.unbindKeyDown('Ctrl+G')
  enterGame:destroy()
  enterGame = nil
  clientBox = nil
  if motdWindow then
    motdWindow:destroy()
    motdWindow = nil
  end
  if loadBox then
    loadBox:destroy()
    loadBox = nil
  end
  if protocolLogin then
    protocolLogin:cancelLogin()
    protocolLogin = nil
  end
  cancelDownload()
  EnterGame = nil
end

function EnterGame.show()
if modules.client.startBox or modules.client.failDownloadBox or modules.client.finishBox or modules.client.failCheckBox then return false end
if modules.client.updateBox and modules.client.updateBox:isVisible() then return false end

if g_game.isLogging() or CharacterList.isVisible() then return false end
  if loadBox or progressWindow then return end
  enterGame:show()
  enterGame:raise()
  enterGame:focus()
end

function EnterGame.hide()
  enterGame:hide()
end

function EnterGame.openWindow()
  if g_game.isOnline() then
    CharacterList.show()
  elseif not g_game.isLogging() and not CharacterList.isVisible() then
    EnterGame.show()
  end
end

function EnterGame.setAccountName(account)
  local account = g_crypt.decrypt(account)
  --local account = g_crypt.xorCrypt(account, 123)
  enterGame:getChildById('accountNameTextEdit'):setText(account)
  enterGame:getChildById('accountNameTextEdit'):setCursorPos(-1)
  enterGame:getChildById('rememberPasswordBox'):setChecked(#account > 0)
end

function EnterGame.setPassword(password)
  local password = g_crypt.decrypt(password)
  --local password = g_crypt.xorCrypt(password, 123)
  enterGame:getChildById('accountPasswordTextEdit'):setText(password)
end

function EnterGame.clearAccountFields()
  local accountText = enterGame:getChildById('accountNameTextEdit')
  local passwordText = enterGame:getChildById('accountPasswordTextEdit')
  if accountText:getText() ~= "" then
     accountText:clearText()
  end
  if passwordText:getText() ~= "" then
     passwordText:clearText()
  end
  enterGame:getChildById('accountNameTextEdit'):focus()
  g_settings.remove('account')
  g_settings.remove('password')

end

function EnterGame.doLogin(cast, cams)
  G.account = enterGame:getChildById('accountNameTextEdit'):getText()
  G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
  G.host = enterGame:getChildById('serverHostTextEdit'):getText()
  G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
  local clientVersion = tonumber("772")
  EnterGame.hide()

  if g_game.isOnline() then
    local errorBox = displayErrorBox(tr('Login Error'), tr('You are already logged in.'))
    connect(errorBox, { onOk = EnterGame.show })
    return
  end

  g_settings.set('host', G.host)
  g_settings.set('port', G.port)
  g_settings.set('client-version', clientVersion)
  g_settings.set('proxy', clientBox:getCurrentOption().text)

  protocolLogin = ProtocolLogin.create()
  protocolLogin.onLoginError = onError
  protocolLogin.onMotd = onMotd
  protocolLogin.onCharacterList = onCharacterList
  protocolLogin.onUpdateNeeded = onUpdateNeeded

  loadBox = displayCancelBox(tr('Please wait'), tr('Your character list is being loaded. Please wait.'))
  connect(loadBox, { onCancel = function(msgbox)
                                  loadBox = nil
                                  protocolLogin:cancelLogin()
                                  EnterGame.show()
                                end })

  g_game.setProtocolVersion(g_game.getClientProtocolVersion(clientVersion))
  g_game.chooseRsa(G.host)

  if modules.game_things.isLoaded() then

    if clientBox:getCurrentOption().text == "Redemption" then
       G.port = "7171"
        elseif clientBox:getCurrentOption().text == "Prosperity" then
           G.port = "7175"
    elseif clientBox:getCurrentOption().text == "War" then
           G.port = "7181"
    elseif clientBox:getCurrentOption().text == "test" then
           G.port = "7177"
    elseif clientBox:getCurrentOption().text == "Encounter" then
           G.port = "7185"
        end

    if cast then
           G.account = ""
        end

        if cams then
           G.account = ""
           G.port = 7194
        end

        protocolLogin:login(G.host, G.port, G.account, G.password)

  else
    loadBox:destroy()
    loadBox = nil
    EnterGame.show()
  end
end

function EnterGame.displayMotd()
  if not motdWindow then
    motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage)
    motdWindow.onOk = function() motdWindow = nil end
  end
end

function EnterGame.setDefaultServer(host, port, protocol)
  local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
  local portTextEdit = enterGame:getChildById('serverPortTextEdit')
  local clientLabel = enterGame:getChildById('clientLabel')
  local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
  local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')

  if hostTextEdit:getText() ~= host then
    hostTextEdit:setText(host)
    portTextEdit:setText(port)
    accountTextEdit:setText('')
    passwordTextEdit:setText('')
  end
end

function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeight)
  local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
  hostTextEdit:setText(host)
  hostTextEdit:setVisible(false)
  hostTextEdit:setHeight(0)
  local portTextEdit = enterGame:getChildById('serverPortTextEdit')
  portTextEdit:setText(port)
  portTextEdit:setVisible(false)
  portTextEdit:setHeight(0)

  local portLabel = enterGame:getChildById('portLabel')
  portLabel:setVisible(false)
  portLabel:setHeight(0)
  local clientLabel = enterGame:getChildById('clientLabel')
  clientLabel:setVisible(false)
  clientLabel:setHeight(0)

  local serverListButton = enterGame:getChildById('serverListButton')
  serverListButton:setVisible(false)
  serverListButton:setHeight(0)
  serverListButton:setWidth(0)

  local rememberPasswordBox = enterGame:getChildById('rememberPasswordBox')

  if not windowWidth then windowWidth = 240 end
  enterGame:setWidth(windowWidth)
  if not windowHeight then windowHeight = 230 end
  enterGame:setHeight(windowHeight)
end

function EnterGame.setServerInfo(message)
  local label = enterGame:getChildById('serverInfoLabel')
  label:setText(message)
end

function EnterGame.disableMotd()
  motdEnabled = false
end
  • thanks you ;), Cluld you please describe step by step how you do it ? please, i have about 20 files. It can very help me. please – rrrrcode May 25 '20 at 18:18
  • @rrrrcode https://stackoverflow.com/a/5040002/7509065 has a quick-and-dirty Python script to do it. Just change `0x71` to `0x25`. – Joseph Sible-Reinstate Monica May 25 '20 at 18:24
  • could you please explain to me how you saw lot of repeating patterns, i opened file with a hex editor and i don't see repeating patterns. Cluld you please in more details why you Xord it by 0x25 ? – rrrrcode May 25 '20 at 18:38
  • @rrrrcode Bytes `0x1cf8` through `0x1d19` are all `0x05`. On a hunch, I guessed that these were spaces, which are `0x20`, so I did `0x05` XOR `0x20` and got `0x25`, and then used that as the key to XOR the whole file with. – Joseph Sible-Reinstate Monica May 25 '20 at 18:40
  • ok, i know now i have last question about repeating patterns i upload screen of my hex editor https://ibb.co/106Nf6f could you please look on it, and help me to find these patterns ? – rrrrcode May 25 '20 at 18:54
  • @rrrrcode Why do you need to find the patterns yourself? I expect that all of the Lua files you got from this project will be XOR'd with the same key. – Joseph Sible-Reinstate Monica May 25 '20 at 18:55
  • yes, but i would like to learn it, I like to know what I do :) and not to write posts again in the future – rrrrcode May 25 '20 at 18:58
  • @rrrrcode Anyway, in the screenshot you posted, some good clues are the repeating strings `KQ@WbDh@` and `IJFDI`. The keyword `local` is really common in Lua, and XORing the bytes of `IJFDI` with `0x25` turns it into `local`. – Joseph Sible-Reinstate Monica May 25 '20 at 19:01
  • do you recommend any other hex editor for it? it look like skipped spaces in my example – rrrrcode May 25 '20 at 19:17
  • 1
    @rrrrcode The hex editor in your screenshot is fine and does not have "skipped spaces". It sounds like you're just not familiar with how hex editors work. – Joseph Sible-Reinstate Monica May 25 '20 at 19:18