为什么 L->l_G->_defaultmeta.value.gc 总是 NULL? [英] Why is L->l_G->_defaultmeta.value.gc always NULL?

查看:15
本文介绍了为什么 L->l_G->_defaultmeta.value.gc 总是 NULL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试破解游戏的 Lua 实现,以扩展游戏模组的内置方法.

为了做到这一点,我尝试劫持一个指向有效lua_State结构的指针,并用它注册新的库.

我现在已经尝试了目标游戏的几个地方/阶段来拦截程序并从中窃取lua_State.我的第一次尝试是在 base_open() 的最后调用 luaL_openlib().这是我第一次得到这个空指针异常:

抛出异常:读取访问冲突.L->l_G->_defaultmeta.value.gc 是 nullptr.

从您可以看到的评论中,

我知道我在这里尝试破解的游戏使用了 "Lua 5.0 的不同版本",但是他们是否改变了垃圾收集的工作方式或其他什么?因为有..

<小时>

还有一点要记住:

游戏已经编译了Lua.我创建的 DLL 有自己的 Lua 5.0.1 编译.当然有可能,当时的游戏开发者决定不只是小幅"改变 Lua,而是大量改变它.我总是假设所有开发人员所做的都是删除一些默认库并添加一些其他内置函数,例如 LOG()WARN() 等.它会如果他们更改了 Lua 核心中的代码,那会很奇怪 - 但我告诉你,只是为了让对 Lua 有想法的人可能会认为这是对我在这里遇到的异常的解释.

解决方案

看起来你的 sizeof(lua_TObject) 确实与游戏的 Lua 使用的不匹配.造成这种差异的一个常见原因是使用浮点数(或整数)作为数字而不是默认的双精度数.我个人没有在 Lua 5.0 中进行过这种更改,但看起来可以通过将 LUA_NUMBER 定义为 float(或 int)来完成.对于 int/float,大小应该是 8,但是对于 double 来说是 16(不是 12,因为 double 需要对齐).

lua_TObject 由一个类型标签 (tt) 和一个值联合组成.该联合中最大的东西通常是 8 字节的双精度值(如果是 64 位,则是 8 字节的指针,但这是 32 位).其他所有内容通常为 4 个字节.监视窗口中的大部分内容看起来都非常有效,但 lua_Objects 看起来很粗略.并且_defaultmeta 直接跟在另一个lua_TObject 之后,所以如果lua_TObject 的大小不同,你的代码和游戏代码就会对这个成员的位置产生分歧._defaultmeta 的 tt 应该是 5 (LUA_TTABLE),但你的看起来可能是一个指针.此外,top、base 和 _registry 的 tt 字段指示将具有指针类型值的其他类型,但 gc 字段指示您的代码看到的是小整数而不是指针.这些可能是相邻 lua_TObjects 的 tt 字段.最重要的是,top 和 base 没有相同的 16 字节对齐方式,它们应该是指向同一个 lua_TObject 数组的指针.

如果您仍然遇到问题,请尝试在修改之前检查您从游戏中获得的 lua_State 对象,并将其与您在自己创建的干净初始化的 lua_State 中看到的 lua_State 进行比较.很明显,指针地址可能不同,游戏可能设置了一些你没有的内容,但还是会跳出一些不一致的地方.

如果您可以访问游戏使用的已编译 Lua 块,您还可以查看这些块的标头信息.这将包含一些有助于匹配 Lua 配置的信息,包括 sizeof(lua_Number).

(但我认为将双打改为浮动可能就足够了.)

它还可以帮助您将调试检查添加到您自己的 Lua 构建中,这可能会在遇到任何有趣的业务时尽早向您发出警告,至少在最初是这样.看起来 Lua 5.0 允许 lua_assert 和 api_check 被 #defined 用于此类目的.

祝你好运!

I am currently trying to hack the Lua implementation of a game in order to extend the built-in methods for game modders.

In order to do so, I try to hijack a the pointer to a valid lua_State struct and register new libraries with it.

I have now tried several places / stages of the target game to intercept the program and steal lua_State from it. My first try was callin in luaL_openlib() at the very end of base_open(). This was the first time I got this null-pointer exception:

Exception thrown: read access violation.

L->l_G->_defaultmeta.value.gc was nullptr.

From the comments you can see, that Egor Sktiptunoff suggested to me moving the entry point of my hack into a user-level function. Since I know, that one of the first functions getting called is dofile(), I stole the lua_State struct from there and passed it to my DLL.

What you see here is the actual code from my injected DLL which I tried to execute at the end of base_open() and dofile() (user-level):

EXTERN_DLL_EXPORT void initialize(lua_State *L)
{
    if (initialized == true) {
        return;
    }

    initialized = true;

    lua_pushvalue(L, LUA_GLOBALSINDEX);          // Works
    luaL_openlib(L, "ext", extension_funcs, 0);  // Crashes with "L->l_G->_defaultmeta.value.gc was nullptr"
}

Below you can find the screenshot of a debug session and the location where the exception gets thrown. The lua_State object is the one that I stole and was passed to e.g. dofile. How can it be that L->l_G->_defaultmeta.value.gc is NULL at this point in time? Is there anything I can do here or is there any explanation for this?

I know that the game which I try to hack here uses a "slightly different version of Lua 5.0", but could it be that they changed the way how garbage collection works or something? Because there is ..


One more thing to keep in mind:

The game has Lua compiled into it. The DLL I created has its own compilation of Lua 5.0.1. There is of course a chance, that the game developers back then decided to not just "sligtly" change Lua, but instead change it a lot. I am always just assuming that all the developers did was removing some default libraries and added some other built-in functions like LOG(), WARN(), etc. It would be strange if they changed code in Lua's core - but I tell you that just so somebody who has an idea about Lua might consider this as an explanation for the exception I am getting here.

解决方案

It really looks like your sizeof(lua_TObject) doesn't match what the game's Lua is using. A common reason for this to be different is using floats (or ints) as numbers instead of the default double. I haven't personally made this change in Lua 5.0, but it looks like it can be done by defining LUA_NUMBER as float (or int). With int/float the size should be 8, but with double it is 16 (not 12 because the double needs to be aligned).

lua_TObject consists of a type tag (tt) along with a value union. The largest thing in that union is usually the 8-byte double (or an 8-byte pointer if 64-bit, but this is 32-bit). Everything else is typically 4 bytes. Most of the stuff in your watch window looks pretty valid, but the lua_Objects look sketchy. And _defaultmeta comes directly after another lua_TObject, so if the size of lua_TObject is different, your code and the game code will disagree about the location of this member. tt for _defaultmeta should be 5 (LUA_TTABLE), but yours looks like it is probably a pointer. Also, the tt fields for top, base, and _registry indicate other types that will have a pointer type value, but the gc field indicates your code is seeing small integers instead of pointers. These are probably tt fields of adjacent lua_TObjects. On top of all that, top and base don't have the same 16-byte alignment, and these are supposed to be pointers into the same lua_TObject array.

If you continue having trouble, try examining the lua_State object you get from the game before you have modified it, and compare it to the lua_State you see in a cleanly initialized lua_State you have made yourself. Obviously, pointer addresses may differ, and the game may be setting up some contents you are not, but some inconsistencies may still jump out.

If you have access to compiled Lua chunks that the game uses, you could also look at the header information of these chunks. This will contain some information that could be helpful in matching your Lua configuration including sizeof(lua_Number).

(But I think there is some chance that changing doubles to floats could be sufficient.)

It may also help you to add debugging checks to your own Lua build that may warn you sooner in the case of any funny business, at least initially. It looks like Lua 5.0 allows for both lua_assert and api_check to be #defined for such purposes.

Good luck!

这篇关于为什么 L->l_G->_defaultmeta.value.gc 总是 NULL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆