assistd / go-ios

MIT License
2 stars 0 forks source link

打包macOS上pkg/dmg文件及macOS开机自启动 #45

Open prife opened 1 year ago

prife commented 1 year ago

参考文档

macOS通用(胖)二进制 Universal(Fat) Binaries

利用该机制,可以将arm64位版本与x86_64版本打成一个胖二进制版本

查看二进制类型:支持的体系架构

lipo -info /path/to/binary

合并两个二进制

lipo bin/haproxy.darwin.x86_64  bin/haproxy.darwin.arm64 -create -output haproxy.darwin

launchd相关

pkg格式

prife commented 1 year ago

pkg vs dmg

dmg

企业微信截图_c3c75bab-795e-4fab-a37c-73d7261c1413 企业微信截图_ce3769d3-07ff-4348-8dbb-1980a5ac01c0

pkg

解包pkg工具

  1. tabby-1.0.187-macos-arm64.pkg,https://github.com/Eugeny/tabby/blob/master/.github/workflows/build.yml,electron项目,参考不方便
  2. HeadSpin-CLI-v202212.68.0.pkg
  3. https://github.com/prife/macos-installer-builder
$ mkdir temp && cd temp
$ pkgutil --expand-full HeadSpin-CLI-v202212.68.0.pkg out

├── Distribution
├── HeadSpin-CLI-v202212.68.0.pkg
│   ├── Bom
│   ├── PackageInfo
│   └── Payload
│       └── hs
├── HeadSpin-Helper-v202212.68.0.pkg
│   ├── Bom
│   ├── PackageInfo
│   ├── Payload
│   │   └── Library
│   │       ├── LaunchDaemons
│   │       │   └── io.headspin.DevTools.Helper.plist
│   │       └── PrivilegedHelperTools
│   │           └── io.headspin.DevTools.Helper
│   └── Scripts
│       └── postinstall
└── Resources
    ├── LICENSE.txt
    └── README.txt

打包pkg

最终决定基于macos-installer-builder,同时基于headpin.pkg和iOA.pkg,构造一个udt专用模板,它具有以下特点

  1. 单个pkg,HeadSpin.pkg内置两个pkg,这会导致打包脚本较负责
  2. 支持二进制命令行工具软链接到/usr/local/bin/目录下
  3. 支持服务开机自启动,类似HeadSpin的DevHelperDaemon,但是使用iOA.pkg类似方式
  4. 支持自动检测更新,类似iOA.pkg
  5. 简化文件,macos-installer-builder内置了一些图片和描述文件,华而不实,移除之
prife commented 1 year ago

headspin工具逆向分析,headspin.pkg安装后会自动执行postinstall安装脚本

$ pkgutil --expand-full HeadSpin-CLI-v202212.68.0.pkg out

├── Distribution
├── HeadSpin-CLI-v202212.68.0.pkg
│   ├── Bom
│   ├── PackageInfo
│   └── Payload
│       └── hs
├── HeadSpin-Helper-v202212.68.0.pkg
│   ├── Bom
│   ├── PackageInfo
│   ├── Payload
│   │   └── Library
│   │       ├── LaunchDaemons
│   │       │   └── io.headspin.DevTools.Helper.plist
│   │       └── PrivilegedHelperTools
│   │           └── io.headspin.DevTools.Helper
│   └── Scripts
│       └── postinstall
└── Resources
    ├── LICENSE.txt
    └── README.txt

这个脚本的内容是

#!/usr/bin/env sh
set -eu
launchctl unload /Library/LaunchDaemons/io.headspin.DevTools.Helper.plist
launchctl load /Library/LaunchDaemons/io.headspin.DevTools.Helper.plist

由于安装过程输入了密码,这个脚本是以root权限进行的,可以看到其中执行了 load,但未执行start操作。io.headspin.DevTools.Helper.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>io.headspin.DevTools.Helper</string>
  <key>MachServices</key>
  <dict>
    <key>io.headspin.DevTools.Helper</key>
    <true/>
  </dict>
  <key>Program</key>
  <string>/Library/PrivilegedHelperTools/io.headspin.DevTools.Helper</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Library/PrivilegedHelperTools/io.headspin.DevTools.Helper</string>
  </array>
</dict>
</plist>

仔细阅读文件内容并测试,发现以下疑点:

  1. 该文件没有配置RunAtLoad字段,也就是说只执行launchd load命令,该进程是不会启动的。事实也是如此,安装pkg后,执行ps -ef | grep headspin,确认无后台进程。并且这意味着开机后Helper程序也不会立刻启动。

尝试手动启动 launchctl start io.headspin.DevTools.Helper,进程未能启动。但如果加sudo launchctl start io.headspin.DevTools.Helper则进程可以正常启动。

那么hs是如何触发Helper进程启动的呢?毕竟hs没有root权限。

  1. 出现了MachServices字段,这个是什么字段呢?
  2. /Library/PrivilegedHelperTools目录下居然还有不少其他文件,如下
    $ ls -l /Library/PrivilegedHelperTools/
    -rwxr-xr-x  1 root  wheel    293120 Dec 14 12:52 com.microsoft.autoupdate.helper
    -rwxr-xr-x  1 root  wheel   1755760 Aug 15 15:50 com.microsoft.office.licensingV2.helper
    -r-xr--r--  1 root  wheel    399616 Jan  5 00:43 com.tencent.iOA.Helper
    -rwxr-xr-x  1 root  wheel  13839296 Dec  9 18:11 io.headspin.DevTools.Helper
    -r-xr--r--  1 root  wheel    219088 Oct 14 10:24 us.zoom.ZoomDaemon

于是一番搜索后发现,原来是PrivilegedHelperTools机制是苹果推出的让普通进程使用受限的root权限的机制。

搜索过程如下:

  1. google搜索PrivilegedHelperTools,资料很少,这篇帖子中提到SMJobBless
  2. 再搜SMJobBless,终于搜到不少资料

总之目前可以99.9%确认,headspin创建127.0.39.xxx 子网ip是借助helper程序提供的root能力创建的。

逆向io.headspin.DevTools.Helper

使用IDA逆向io.headspin.DevTools.Helper,可发现其同样使用go语言实现。

企业微信截图_bbd7e538-5bfc-4b2f-ae7e-6723a63105e1

待进一步研究