调研
检测方法:通过低权限开启对应工具的Service,如果在锁屏时可以正常连接,那么说明可能可以运行在单独用户session中
- TeamViewer,尝试多次未果,无法运行在单独的用户session中
- VNC,可以开启多个session
- Vine VNC Server,官方声明可以开启多个Session的,且为用户态解决方案
- AnyDesk,可低权限运行
结论:理论上完全可行
逆向AnyDesk
- 首先从端口下手
- AnyDesk监听在7070端口,且无法改变
- 全局搜索立即数7070,可以定位到监听端口对应配置选项为ad.anynet.listen_port
- 配置选项为Premium License专属,从后台生成相应安装包
- 配置在入口点处解密并解析,随后被用在各种地方
- 同时发现有一份疑似默认配置在程序中内置,尝试直接修改其中的listen_port为新端口,发现可行
- 同时注意到AnyDesk不从/Applications中执行时,会认为自己运行于单个session,命令行会由
--service
变为--local-service
- 端口问题解决,但多用户同时运行AnyDesk时出现了各种冲突情况
- 一个用户远程连接后,会在另一个用户的session里面弹出对话框询问是否授权
- 如果终端登录有其他用户,则会控制对应用户的屏幕
- 经常互相冲突导致连不上
- 多管齐下进行逆向
- Log分析:
- 了解到log的输出位置在/var/log/anydesk.trace
- 程序在输出找不到Free Login Slot后gg
- log与fiber调度相关
- 崩溃点调试:
- 挂上调试器,通过在Log函数打断点,得知程序崩溃位置调用栈
- 可以看到程序kill了一个进程后判断了一下退出
- 程序中有字符串加密,导致难以通过Log信息进行定位
- Trace:
- 关闭SIP,使用MacOS的strace——dtruss进行trace
- 可以看到程序list了/tmp/anydesk,前往查看可知内部有大量ad_XXXX的管道
- 回溯调试:
- 结合上面三个分析进行逆向,发现程序从一块内存中获取已运行的AnyDesk的进程信息
- 通过内存断点回溯查找,看到程序mmap了一块共享内存
- 共享内存的名称与/tmp/anydesk文件夹下面的文件对应,为ad_版本号_(gsystem|lsystem)_内存用途
- 共享内存中存储了每个AnyDesk的进程pid、进程类型、进程uid
解决方案:直接将lsystem替换为别的内容即可
综合解决方案:
- 替换ad.anynet.listen_port=的默认配置为对应端口
- 替换lsystem为其他唯一值
部署
- AnyDesk的local端在断网后会自动退出
- 而这种每个用户的AnyDesk需要在用户interactive登录后才能运行,因此不能使用launchctl
- 尝试通过shell script循环启动local service作为登录项,发现执行不了
- 通过自动操作(automator)生成一个执行shell脚本的.app,然后就可以自动启动了
- 通过automator启动的local service似乎权限也跟着automator走,需要重新配置权限