actboy168 / lua-debug

Lua Debug Adapter for Visual Studio Code
MIT License
439 stars 95 forks source link

macos add process inject #218

Closed fesily closed 1 year ago

actboy168 commented 1 year ago

没有考虑在arm64的平台上注入x86_64的进程?

fesily commented 1 year ago

根本就没有Rosetta 2的有关资料,无从下手 完全闭源的

actboy168 commented 1 year ago

根本就没有Rosetta 2的有关资料,无从下手 完全闭源的

你准备一个x86_64的process_inject_helper,用它来注入x86_64的进程,应该就可以了吧

fesily commented 1 year ago

根本就没有Rosetta 2的有关资料,无从下手 完全闭源的

你准备一个x86_64的process_inject_helper,用它来注入x86_64的进程,应该就可以了吧

根本不可以, Rosetta是运行在用户态的jit转义器,对于所有内核函数来说他只认为这个进程是arm64的,除了特定的一个syscall修改了m1芯片上的内存模型标志. 所以这个时候x64进程内的所有导出函数地址是跟arm64的地址完全不一样的,现在的代码是可以注入成功,但是你也加载不了x64的动态库,因为原生的dlopen根本就不会加载不同架构的代码. 必须要找到转义成x86的dlopen的地址,并且这个地址上使用Rosetta的专有x64 ABI调用才行.

总结一下,

  1. 现在无法找到转义后的函数地址
  2. 专用的ABI约定不知道是什么
  3. shellcode也必须是arm64的,根本无法注入x64的代码,因为内核不认识
fesily commented 1 year ago

当然还是有办法的,直接调用LLDB通过MI协议让LLDB去注入就完事了.

fesily commented 1 year ago

主要是运行在Rosetta的x64程序,lldb调试的时候,他会启动一个专门debug server中转所有的请求, 这个debug server要是有源码也就好说了,问题是开源的APPLE-LLVM项目不存在这个工程,所以这玩意也是闭源的

actboy168 commented 1 year ago

根本就没有Rosetta 2的有关资料,无从下手 完全闭源的

你准备一个x86_64的process_inject_helper,用它来注入x86_64的进程,应该就可以了吧

根本不可以, Rosetta是运行在用户态的jit转义器,对于所有内核函数来说他只认为这个进程是arm64的,除了特定的一个syscall修改了m1芯片上的内存模型标志. 所以这个时候x64进程内的所有导出函数地址是跟arm64的地址完全不一样的,现在的代码是可以注入成功,但是你也加载不了x64的动态库,因为原生的dlopen根本就不会加载不同架构的代码. 必须要找到转义成x86的dlopen的地址,并且这个地址上使用Rosetta的专有x64 ABI调用才行.

总结一下,

  1. 现在无法找到转义后的函数地址
  2. 专用的ABI约定不知道是什么
  3. shellcode也必须是arm64的,根本无法注入x64的代码,因为内核不认识

不行也无所谓了。由于我目前还无法运行,所以我不知道在arm64上attach x86_64的进程会发生什么。只要能返回错误,而不是无缘无故卡死或者挂掉之类的就OK。

actboy168 commented 1 year ago

这个PR没有包含dobby和launch的修改,所以它只是可以注入进程,但不能把调试器加载起来?

fesily commented 1 year ago

这个PR没有包含dobby和launch的修改,所以它只是可以注入进程,但不能把调试器加载起来?

actboy168 commented 1 year ago

这样我无法验证这些代码,你可以把#216 里最初版本的launch移过来。

fesily commented 1 year ago

这样我无法验证这些代码,你可以把#216 里最初版本的launch移过来。

这个简单,你直接随便生成一个launcher.so,里面导出attach函数就行。放在publish/bin就可以看到效果了

fesily commented 1 year ago

我加了一个测试用例

fesily commented 1 year ago

很奇怪,我在本机上使用luamake -platform darwin-x64是正常编译的,CI是不能通过的,是不是luamake版本问题?

actboy168 commented 1 year ago

我依然无法跑起来。我用的配置是

        {
            "type": "lua",
            "request": "launch",
            "name": "Test",
            "luaVersion": "latest",
            "stopOnEntry": true,
            "inject": "hook",
            "runtimeExecutable": "${command:extensionPath}actboy168.lua-debug-1.61.0-darwin-arm64/runtime/darwin-arm64/lua-latest/lua",
            "runtimeArgs": "test.lua",
        },

简单调试一下,是task_for_pid返回失败了。

actboy168 commented 1 year ago

很奇怪,我在本机上使用luamake -platform darwin-x64是正常编译的,CI是不能通过的,是不是luamake版本问题?

因为你把一些文件从.cpp改成.cc,但编译脚本里还是cpp。

就全用cpp就好,一会cc一会cpp到,只会搞乱了。

fesily commented 1 year ago

话说我不是加了一个inject的测试用例,你不需要在把之前的代码merge进来,只用看测试用例就好了. 测试过程是启动一个死循环的lua进程,注入的so会关闭这个进程并且删除自己

actboy168 commented 1 year ago

你的测试我跑通过了。你的测试不能覆盖所有的情形。比如我遇到错误就没有覆盖。

fesily commented 1 year ago

你的测试我跑通过了。你的测试不能覆盖所有的情形。比如我遇到错误就没有覆盖。

那是现在的代码跟测试代码压根不是一回事 这个测试当然仅仅是测试注入的功能.测试怎么调用注入功能又是另外一回事了

actboy168 commented 1 year ago

所以加一个launcher,做完整的测试还是很有必要的

fesily commented 1 year ago

这个

bingo

fesily commented 1 year ago

image

你测试的时候,注入会出现提权请求窗口吗

actboy168 commented 1 year ago

image

你测试的时候,注入会出现提权请求窗口吗

有。我刚刚又测试了一次,没有在task_for_pid失败,但也没有加载到launcher。

fesily commented 1 year ago

image 你测试的时候,注入会出现提权请求窗口吗

有。我刚刚又测试了一次,没有在task_for_pid失败,但也没有加载到launcher。 我虚拟机问题,虚拟机里的MAC有点问题,裸机没问题 image 注入成功的,原始的launcher肯定不会成功,因为缺少很多符号 image

actboy168 commented 1 year ago

不知为何我的机器的表现和你的有如此大差别。可能是我机器上的杀毒软件的捣鬼? 所以我放弃验证了。你觉得没问题了,我就合并吧。

fesily commented 1 year ago

不知为何我的机器的表现和你的有如此大差别。可能是我机器上的杀毒软件的捣鬼? 所以我放弃验证了。你觉得没问题了,我就合并吧。

我在测试用例里添加了LLDB,昨天提交的有几个地方写错了.现在应该是OK的

actboy168 commented 1 year ago

lldb需要设置inject:lldb才能用?为什么不为默认或者自动选择呢

fesily commented 1 year ago

当然可以改成自动

两点吧 主要为了wine环境做准备,之后linux也先准备一个gdb注入的方式 不是每台环境都有lldb和gdb

fesily commented 1 year ago

我觉得现在是时候合并了