lua_injection.lua 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. --[[
  2. Sample output: https://pastebin.com/raw/ciay6HXj
  3. File name: "no message" (no extension)
  4. Instructions:
  5. Symlink this file into the GI working directory
  6. That's usually where GenshinImpact.exe is.
  7. Function description:
  8. sb_1184180413 c-call function with args
  9. Hints for modifying this script:
  10. 1) There is mostly no error handling in GI!
  11. 2) Run the script in Lua CLI (i.e. 'lua "no message"') to check for syntax errors
  12. 3) Uncomment functions until you see basic log information again
  13. ]]
  14. local HOOK_RECURSIVE = true -- more precise hooks, but may stall the game
  15. local LH = {} -- file-wide access
  16. local function dump(val, depth, seen)
  17. depth = depth or 0
  18. seen = seen or {}
  19. if seen[val] then return "<CIRCULAR REF>" end
  20. if depth > 10 then return "<TOO DEEP>" end
  21. if val == nil then return "nil" end
  22. local txt = {}
  23. if type(val) == "table" then
  24. seen[val] = true
  25. txt[#txt + 1] = "{"
  26. for k, v in pairs(val) do
  27. txt[#txt + 1] = string.rep("\t", depth + 1) ..
  28. ("[\"%s\"] = %s"):format(tostring(k), dump(v, depth + 1, seen))
  29. end
  30. txt[#txt + 1] = string.rep("\t", depth) .. "}"
  31. elseif type(val) == "string" then
  32. txt[#txt + 1] = '"' .. val:gsub('\n', "$LF"):gsub('"', '\\"') .. '"'
  33. else
  34. txt[#txt + 1] = tostring(val)
  35. end
  36. return table.concat(txt, "\n")
  37. end
  38. local F = io.open("lualog_" .. os.date("%H%M-%S") .. ".txt", "a")
  39. F:write("=== LOG START: " .. os.date() .. "\n")
  40. local function LOG(msg)
  41. F:write(msg)
  42. F:write("\n")
  43. end
  44. -- HOOK FUNCTIONS
  45. table.unpack = table.unpack or unpack -- Lua compatibility
  46. local hooked = {}
  47. local function hook_wrapper(func, name, ...)
  48. LOG(("> CALL %s = %s"):format(name, dump({...}, 1)))
  49. local ret_vals = {func(...)}
  50. LOG(("< RET %s = %s"):format(name, dump(ret_vals, 1)))
  51. LH.interval_func()
  52. return table.unpack(ret_vals)
  53. end
  54. local function hook_recursive(tb, k, v, path)
  55. path = path or ""
  56. v = v or tb[k] or tb
  57. if hooked[v] then
  58. return
  59. end
  60. -- If a custom table is provided, hook all functions
  61. if type(v) == "table" then
  62. if not HOOK_RECURSIVE and v ~= _G then
  63. return
  64. end
  65. if v == table or v == io or v == math
  66. or v == debug or v == string then
  67. return
  68. end
  69. -- Traverse table to hook all functions
  70. hooked[v] = true
  71. for k2, v2 in pairs(v) do
  72. if type(v2) == "table" then
  73. hook_recursive(v, k2, v2, path..k2..".")
  74. else
  75. hook_recursive(v, k2, v2, path)
  76. end
  77. end
  78. return
  79. end
  80. if type(v) ~= "function" then
  81. return
  82. end
  83. -- Do not hook common functions to avoid recursion
  84. if k == "tostring" or k == "type" or k == "sethook" or k == "typeof"
  85. or k == "ipairs" or k == "pairs" or k == "next" or k == "select"
  86. or k == "print"
  87. or k == "rawset" or k == "rawget"
  88. or k == "setmetatable" or k == "getmetatable" then
  89. return
  90. end
  91. LOG("HOOK " .. path .. k)
  92. tb[k] = function(...)
  93. return hook_wrapper(v, path .. k, ...)
  94. end
  95. hooked[tb[k]] = true
  96. end
  97. -- INTERVAL-TRIGGERED FUNCTIONS
  98. -- socket.gettime() cannot be loaded
  99. local last_time = 0
  100. local get_time = os.time
  101. local set_hook = debug.sethook
  102. LH.interval_func = function()
  103. if get_time() < last_time + 2 then
  104. return
  105. end
  106. last_time = get_time()
  107. LOG("=== DUMP OF _G")
  108. LOG(dump(_G))
  109. hook_recursive(_G)
  110. -- Manual function triggering
  111. set_hook(LH.interval_func, "r", 1000)
  112. end
  113. set_hook(LH.interval_func, "rl", 1)
  114. hook_recursive(_G)
  115. rawget(_G, "test call, returns nil")