actboy168 / lua-debug

Lua Debug Adapter for Visual Studio Code
MIT License
431 stars 93 forks source link

New launcher #222

Closed fesily closed 1 year ago

fesily commented 1 year ago

test:

fesily commented 1 year ago

什么时候方便的话,我们联调一下 我试了别人的三台m1都没有出现root权限下task_for_pid error,都是系统13,你是什么版本的系统. 有一种可能,你目前的系统需要签名,你可以试试自签名launcher和inject.

actboy168 commented 1 year ago

操作系统是最新的。可能是我的杀毒软件搞的鬼。之前我就发觉它一些特别之处,比如xcode无法启动ios的app。

fesily commented 1 year ago

那你确定一下,是不是杀毒软件搞的鬼,我这边的几台mac是都没有杀毒软件的

actboy168 commented 1 year ago

有空我再研究下

fesily commented 1 year ago

这种模式已经可以了

        {
            "name": "attach",
            "request": "attach",
            "stopOnEntry": true,
            "type": "lua",
            "luaVersion": "jit",
            "processName": "lua"
        }
fesily commented 1 year ago
        {
            "name": "attach",
            "request": "attach",
            "stopOnEntry": true,
            "type": "lua",
            "luaVersion": "jit",
            "processName": "lua",
            "inject": "lldb",
        },

也是ok

actboy168 commented 1 year ago

这个和 #216 的区别,只是windows下用了旧代码,macos用新代码?

actboy168 commented 1 year ago

symbol_resolver目录下的几个文件感觉挺多余的,全部合并到lua_resolver.cpp里去好了

fesily commented 1 year ago

这个和 #216 的区别,只是windows下用了旧代码,macos用新代码?

基本上是这样,多了几个测试用例,核心代码就是这样,并且gumpp变成子模块了

fesily commented 1 year ago

symbol_resolver目录下的几个文件感觉挺多余的,全部合并到lua_resolver.cpp里去好了

这里文件夹下我删了特征码扫描的部分,因为这块代码也挺大的,所以现在看起来抽象没什么用

actboy168 commented 1 year ago

这个和 #216 的区别,只是windows下用了旧代码,macos用新代码?

基本上是这样,多了几个测试用例,核心代码就是这样,并且gumpp变成子模块了

如果是这样还不如把旧代码删了。我现在只能跑windows的版本,如果windows和这个pr无关,我就完全无法验证了。

fesily commented 1 year ago

这个和 #216 的区别,只是windows下用了旧代码,macos用新代码?

基本上是这样,多了几个测试用例,核心代码就是这样,并且gumpp变成子模块了

如果是这样还不如把旧代码删了。我现在只能跑windows的版本,如果windows和这个pr无关,我就完全无法验证了。

也行啊,我是按之前聊的,先确定macos🆗在合并windows.

fesily commented 1 year ago

测试的时候暂时不要用launcher.inject的方式,我压根就没测试那种

fesily commented 1 year ago

这个和 #216 的区别,只是windows下用了旧代码,macos用新代码?

基本上是这样,多了几个测试用例,核心代码就是这样,并且gumpp变成子模块了

如果是这样还不如把旧代码删了。我现在只能跑windows的版本,如果windows和这个pr无关,我就完全无法验证了。

我将关闭之前的pr, 将windows部分合并进来

fesily commented 1 year ago

就剩最后一个我没通过了,macos中launcher模式好像压根新建不了进程。

actboy168 commented 1 year ago

就剩最后一个我没通过了,macos中launcher模式好像压根新建不了进程。

我之前测的就是launch

fesily commented 1 year ago

就剩最后一个我没通过了,macos中launcher模式好像压根新建不了进程。

我之前测的就是launch

我明天在看一下哪里出错了,我之前就没测过这个模式,现在attach都很🆗

actboy168 commented 1 year ago

现在编译有很多警告

fesily commented 1 year ago

现在编译有很多警告

什么警告,windows下吗,frida-gum.h的编码错误吧.那个不用理会.其他我看了下也没有啊

actboy168 commented 1 year ago

现在编译有很多警告

什么警告,windows下吗,frida-gum.h的编码错误吧.那个不用理会.其他我看了下也没有啊

3rd/frida_gum/windows-x86_64\frida-gum.h(18379): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
3rd/frida_gum/gumpp/src/internal/override_gumdbghelp.c(160): warning C4996: 'wcscpy': This function or variable may be unsafe. Consider using wcscpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
3rd/frida_gum/gumpp/src/invocationlistener.cpp(165): warning C5051: 特性“noinline”至少需要“/std:c++20”;已忽略
src\launcher\hook\vmhook_template.hpp(24): warning C4390: “;”: 找到空的受控语句;这是否是有意的?
LINK : warning LNK4098: 默认库“LIBCMT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library

解决不了的警告,就禁用它

fesily commented 1 year ago

现在编译有很多警告

什么警告,windows下吗,frida-gum.h的编码错误吧.那个不用理会.其他我看了下也没有啊

3rd/frida_gum/windows-x86_64\frida-gum.h(18379): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
3rd/frida_gum/gumpp/src/internal/override_gumdbghelp.c(160): warning C4996: 'wcscpy': This function or variable may be unsafe. Consider using wcscpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
3rd/frida_gum/gumpp/src/invocationlistener.cpp(165): warning C5051: 特性“noinline”至少需要“/std:c++20”;已忽略
src\launcher\hook\vmhook_template.hpp(24): warning C4390: “;”: 找到空的受控语句;这是否是有意的?
LINK : warning LNK4098: 默认库“LIBCMT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library

解决不了的警告,就禁用它

我去为什么咱们看到的结果不一样. 你什么vc版本,vc143的?

actboy168 commented 1 year ago

我去为什么咱们看到的结果不一样. 你什么vc版本,vc143的?

msvc 17.5.0

fesily commented 1 year ago

我去为什么咱们看到的结果不一样. 你什么vc版本,vc143的?

msvc 17.5.0

OK了

fesily commented 1 year ago

我发现一个问题,在attach模式下launcher在已有进程内是得不到很多配置的.因为现在很多配置你可以看到直接用的getenv环境变量来传递的. 我的想法是lua-debug在文件中把配置信息填好,launcher直接去读文件,就类型与现在的IPC功能,在这个基础上进行扩展. 不过我感觉不需要这个PR里实行

actboy168 commented 1 year ago

有什么配置?

fesily commented 1 year ago

有什么配置?

已有的设定配置:

  1. LUA_DEBUG_VERSION:指定lua的版本值为:jit 5.1 5.2 5.3 5.4 latest
  2. LUA_DEBUG_HOOK_ENTRY:指定hook哪些函数以用来覆盖unknow中的默认的设置,值形式为[lua版本.][函数名];[lua版本.][函数名];... 举个例子: lua51.lua_settop;lua_pcall;luajit.lua_call 这种情况下将根据luaversion来决定使用哪些hook的函数名
  3. LUA_DEBUG_SIGNATURE: 指定函数特征吗,格式[lua版本.][函数名]=“?? 99 ff”;[lua版本.][函数名]=“?? 99 ff”;....

现在第三个未使用

actboy168 commented 1 year ago

有什么配置?

已有的设定配置:

  1. LUA_DEBUG_VERSION:指定lua的版本值为:jit 5.1 5.2 5.3 5.4 latest
  2. LUA_DEBUG_HOOK_ENTRY:指定hook哪些函数以用来覆盖unknow中的默认的设置,值形式为[lua版本.][函数名];[lua版本.][函数名];... 举个例子: lua51.lua_settop;lua_pcall;luajit.lua_call 这种情况下将根据luaversion来决定使用哪些hook的函数名
  3. LUA_DEBUG_SIGNATURE: 指定函数特征吗,格式[lua版本.][函数名]=“?? 99 ff”;[lua版本.][函数名]=“?? 99 ff”;....

现在第三个未使用

这个可以之后再做。就这个PR来说,我觉得可以先去掉。

fesily commented 1 year ago

LUA_DEBUG_SIGNATURE代码已经删掉了

actboy168 commented 1 year ago

LUA_DEBUG_SIGNATURE代码已经删掉了

其他的getenv也先删了吧

fesily commented 1 year ago

我确定是launcher模式的问题, 我复现了你之前的错误. 连LLDB都无法附加到这个进程里. 这个console模式是内嵌在vscode进程里的吗?

actboy168 commented 1 year ago

console模式是用了bee的api来启动进程。

你可以先试试用launch模式启动一个进程,能不能attach到这个进程?

现在的流程是先spawn一个暂停状态的进程,调用inject,然后让进程恢复运行。这个步骤对windows来说是没问题的,但可能macos是无法inject一个完全没用运行过的进程?

fesily commented 1 year ago

首先之前的task_for_pid错误是因为lua进程已经执行完毕了,按照你之前的逻辑,是需要暂停方式启动来保证inject时候进程一定还存活

fesily commented 1 year ago

确定是因为POSIX_SPAWN_START_SUSPENDED标志导致的 POSIX_SPAWN_START_SUSPENDED在macos上是停止在dyld::start函数之前,这个时候什么依赖库都没有加载. 时机完全不对,使用不了任何功能

fesily commented 1 year ago

两个平台两种模式可以用了

actboy168 commented 1 year ago

如果不能在inject前把进程停住的话,就可能会出现无法将调试器暂停在第一行。

fesily commented 1 year ago

那麻烦了,需要加入ptrace,加入中断替换指令,还得手工找main函数入口,

粗暴一点的方式就是直接在启动进程之后在启动一个lldb来在进程的main函数的时候加载进去

actboy168 commented 1 year ago

听起来用ptrace比较好一点,这个可以下一步再做。

actboy168 commented 1 year ago

我的macos上没有wget,但是curl似乎是默认自带的。所以用curl比较好?

fesily commented 1 year ago

两者没差别,我记得wget是在linux默认的,curl在powershell不太对

actboy168 commented 1 year ago

每个平台可以用不同的

fesily commented 1 year ago

macos下launcher模式现在强制用lldb执行.我刚才仔细检查了一下出错的地方, 准确说那个时间点不能执行线程注入.除非使用DYLD_INSERT_LIBRARIES,但是这个功能不一定在任何进程内有效,进程可以自己屏蔽掉这个功能

fesily commented 1 year ago

现在的代码就算告一段落了.没有问题就不再继续修改了 下一步路线:

  1. 修复windows的注入器
  2. 加入特征吗扫描
  3. 在构建时生成默认的特征库
actboy168 commented 1 year ago

为什么windows和macos查找lua模块的代码是不同的?

fesily commented 1 year ago

为什么windows和macos查找lua模块的代码是不同的?

可以一样,删掉Windows部分,

fesily commented 1 year ago

为什么windows和macos查找lua模块的代码是不同的?

可以一样,删掉Windows部分,

Windows可以一次调用匹配函数,其他平台的都不行

fesily commented 1 year ago

关于进程中存在多个lua模块的问题,应该需要正确处理 的确有可能会出现多个lua模块在进程中.


有以下的解决方法:

  1. 每个模块都加载调试器
  2. 由用户配置项来指定lua版本号
  3. 使用查找到的第一个模块
actboy168 commented 1 year ago

关于进程中存在多个lua模块的问题,应该需要正确处理 的确有可能会出现多个lua模块在进程中.

有以下的解决方法:

  1. 每个模块都加载调试器
  2. 由用户配置项来指定lua版本号
  3. 使用查找到的第一个模块

嗯,我觉得暂时可以先用方案3就行了。

至于比较完善的方案,我觉得是方案2,有某种配置来让用户指定调试哪个lua模块;然后还可以attach多个实例来同时调试多个lua模块。

fesily commented 1 year ago

下一步吧

actboy168 commented 1 year ago

现在调试器加载的时候(call attach.lua),可能luaL_openlibs还没调用,所以前几次attach.lua会失败,直到某一次luaL_openlibs调用后才会成功。

可能的解决办法:

  1. 确保luaL_openlibs之后,再call attach.lua。
  2. 增加一个测试lua,检测需要的函数都已经存在,再call attach.lua。
  3. 调试器加载代码不依赖任何标准库函数。debugger内的大多数代码是在检测lua version、arch、os等,这些launcher都另一套逻辑在做,做两次没必要也可能导致两次计算不一致。然后可能需要写几个c函数(例如load remotedebug.dll)供attach.lua使用。
fesily commented 1 year ago

现在调试器加载的时候(call attach.lua),可能luaL_openlibs还没调用,所以前几次attach.lua会失败,直到某一次luaL_openlibs调用后才会成功。

可能的解决办法:

  1. 确保luaL_openlibs之后,再call attach.lua。
  2. 增加一个测试lua,检测需要的函数都已经存在,再call attach.lua。
  3. 调试器加载代码不依赖任何标准库函数。debugger内的大多数代码是在检测lua version、arch、os等,这些launcher都另一套逻辑在做,做两次没必要也可能导致两次计算不一致。然后可能需要写几个c函数(例如load remotedebug.dll)供attach.lua使用。

现在调试器加载的时候(call attach.lua),可能luaL_openlibs还没调用,所以前几次attach.lua会失败,直到某一次luaL_openlibs调用后才会成功。

可能的解决办法:

  1. 确保luaL_openlibs之后,再call attach.lua。
  2. 增加一个测试lua,检测需要的函数都已经存在,再call attach.lua。
  3. 调试器加载代码不依赖任何标准库函数。debugger内的大多数代码是在检测lua version、arch、os等,这些launcher都另一套逻辑在做,做两次没必要也可能导致两次计算不一致。然后可能需要写几个c函数(例如load remotedebug.dll)供attach.lua使用。

首先luaL_openlibs不一定被调用,人家的使用方式可以只使用特定的几个库,所以不能依赖这个行为的成立. 最保险的做法就是我们自己调用luaL_openlibs.因为调试器所需要的API即使独立出去做一套,后面宿主环境不加载luaL_openlibs照样起不来. 不过我觉得这种非常非常特殊的情况还是暂时不用理会了.可以以后做个配置来处理

综上,现在最合理的方式就是第二条,添加一个测试lua