.. | ||
arm64-basic-assembly.md | ||
README.md |
macOS应用程序 - 检查、调试和模糊测试
☁️ HackTricks云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一家网络安全公司工作吗?你想在HackTricks中看到你的公司广告吗?或者你想获得PEASS的最新版本或下载PDF格式的HackTricks吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品 - The PEASS Family
- 获得官方PEASS和HackTricks周边产品
- 加入 💬 Discord群组 或 Telegram群组 或 关注我在Twitter上的🐦@carlospolopm。
- 通过向 hacktricks repo 和 hacktricks-cloud repo 提交PR来分享你的黑客技巧。
静态分析
otool
otool -L /bin/ls #List dynamically linked libraries
otool -tv /bin/ps #Decompile application
objdump
objdump
是一个用于检查可执行文件和目标文件的工具。它可以显示文件的各种信息,包括文件头、节头、符号表和重定位表等。通过使用objdump
,我们可以深入了解文件的结构和内容,从而进行调试和分析。
用法
objdump [选项] <文件>
选项
-d
:显示反汇编代码-t
:显示符号表-r
:显示重定位表-h
:显示节头-x
:显示全部信息-S
:显示源代码和反汇编代码
示例
显示文件的反汇编代码:
objdump -d <文件>
显示文件的符号表:
objdump -t <文件>
显示文件的重定位表:
objdump -r <文件>
显示文件的节头:
objdump -h <文件>
显示文件的全部信息:
objdump -x <文件>
显示文件的源代码和反汇编代码:
objdump -S <文件>
通过使用objdump
,我们可以更好地理解文件的内部结构和功能,从而帮助我们进行调试和分析。
objdump -m --dylibs-used /bin/ls #List dynamically linked libraries
objdump -m -h /bin/ls # Get headers information
objdump -m --syms /bin/ls # Check if the symbol table exists to get function names
objdump -m --full-contents /bin/ls # Dump every section
objdump -d /bin/ls # Dissasemble the binary
jtool2
该工具可以用作codesign、otool和objdump的替代品,并提供了一些额外的功能。
# Install
brew install --cask jtool2
jtool2 -l /bin/ls # Get commands (headers)
jtool2 -L /bin/ls # Get libraries
jtool2 -S /bin/ls # Get symbol info
jtool2 -d /bin/ls # Dump binary
jtool2 -D /bin/ls # Decompile binary
# Get signature information
ARCH=x86_64 jtool2 --sig /System/Applications/Automator.app/Contents/MacOS/Automator
Codesign
Codesign(代码签名)是macOS中的一种安全机制,用于验证应用程序的身份和完整性。通过对应用程序进行数字签名,可以确保应用程序未被篡改或恶意注入。
在macOS中,每个应用程序都必须经过代码签名才能被系统信任和运行。签名是使用开发者的私钥对应用程序进行加密的过程,以确保应用程序的完整性和来源可信。
通过验证应用程序的签名,macOS可以确保应用程序来自可信的开发者,并且没有被篡改。如果应用程序的签名无效或缺失,macOS会发出警告并阻止应用程序的运行。
Codesign还可以用于验证应用程序的权限。开发者可以使用代码签名来指定应用程序所需的特定权限,例如访问文件系统、网络或其他系统资源。这样,用户可以在安装应用程序之前,清楚地知道应用程序将要访问的权限范围。
总之,Codesign是macOS中一种重要的安全机制,用于验证应用程序的身份、完整性和权限。通过对应用程序进行数字签名,可以确保应用程序的来源可信,并且可以限制应用程序的权限范围。
# Get signer
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"
# Check if the app’s contents have been modified
codesign --verify --verbose /Applications/Safari.app
# Get entitlements from the binary
codesign -d --entitlements :- /System/Applications/Automator.app # Check the TCC perms
# Check if the signature is valid
spctl --assess --verbose /Applications/Safari.app
# Sign a binary
codesign -s <cert-name-keychain> toolsdemo
SuspiciousPackage
SuspiciousPackage 是一个有用的工具,可以在安装之前检查 .pkg 文件(安装程序)并查看其中的内容。
这些安装程序包含 preinstall
和 postinstall
的 bash 脚本,恶意软件作者通常会滥用这些脚本来持久化****恶意软件。
hdiutil
这个工具允许将苹果磁盘映像(.dmg)文件挂载起来,在运行任何内容之前进行检查:
hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg
它将被挂载在/Volumes
目录下。
Objective-C
元数据
{% hint style="danger" %} 请注意,使用Objective-C编写的程序在编译为Mach-O二进制文件时会保留它们的类声明。这些类声明包括以下信息: {% endhint %}
- 类
- 类方法
- 类实例变量
您可以使用class-dump获取这些信息:
class-dump Kindle.app
函数调用
当在使用Objective-C的二进制文件中调用函数时,编译后的代码不会直接调用该函数,而是调用**objc_msgSend
**。这个函数会调用最终的函数:
这个函数期望的参数是:
- 第一个参数(self)是“指向接收消息的类的实例的指针”。简单来说,它是方法被调用的对象。如果方法是类方法,这将是类对象的一个实例(作为一个整体),而对于实例方法,self将指向作为对象的类的一个实例。
- 第二个参数(op)是“处理消息的方法的选择器”。简单来说,这只是方法的名称。
- 剩下的参数是方法所需的任何值(op)。
参数 | 寄存器 | (对于)objc_msgSend |
---|---|---|
第一个参数 | rdi | self:方法被调用的对象 |
第二个参数 | rsi | op:方法的名称 |
第三个参数 | rdx | 方法的第一个参数 |
第四个参数 | rcx | 方法的第二个参数 |
第五个参数 | r8 | 方法的第三个参数 |
第六个参数 | r9 | 方法的第四个参数 |
第七个及以上参数 | rsp+ |
方法的第五个及以上参数 |
Swift
对于Swift二进制文件,由于与Objective-C兼容,有时可以使用class-dump提取声明,但并非总是有效。
使用**jtool -l
或otool -l
命令行可以找到以__swift5
**前缀开头的多个部分:
jtool2 -l /Applications/Stocks.app/Contents/MacOS/Stocks
LC 00: LC_SEGMENT_64 Mem: 0x000000000-0x100000000 __PAGEZERO
LC 01: LC_SEGMENT_64 Mem: 0x100000000-0x100028000 __TEXT
[...]
Mem: 0x100026630-0x100026d54 __TEXT.__swift5_typeref
Mem: 0x100026d60-0x100027061 __TEXT.__swift5_reflstr
Mem: 0x100027064-0x1000274cc __TEXT.__swift5_fieldmd
Mem: 0x1000274cc-0x100027608 __TEXT.__swift5_capture
[...]
你可以在这篇博客文章中找到关于这些部分存储的信息的更多详细信息。
打包的二进制文件
- 检查高熵
- 检查字符串(如果几乎没有可理解的字符串,则可能是打包的)
- MacOS的UPX打包程序会生成一个名为"__XHDR"的部分
动态分析
{% hint style="warning" %}
请注意,为了调试二进制文件,需要禁用SIP(csrutil disable
或csrutil enable --without debug
),或者将二进制文件复制到临时文件夹中,并使用codesign --remove-signature <binary-path>
删除签名,或者允许对二进制文件进行调试(可以使用此脚本)
{% endhint %}
{% hint style="warning" %}
请注意,为了在macOS上对系统二进制文件(如cloudconfigurationd
)进行插桩,必须禁用SIP(仅删除签名不起作用)。
{% endhint %}
统一日志
MacOS会生成大量日志,当运行应用程序时,这些日志非常有用,可以帮助理解应用程序在做什么。
此外,有一些日志会包含标签<private>
,以隐藏一些用户或计算机可识别的信息。但是,可以安装证书来显示这些信息。请按照这里的说明进行操作。
Hopper
左侧面板
在hopper的左侧面板中,可以看到二进制文件的符号(Labels),过程和函数的列表(Proc)以及字符串(Str)。这些不是所有的字符串,而是在Mac-O文件的几个部分中定义的字符串(如_cstring或objc_methname
)。
中间面板
在中间面板中,可以看到反汇编代码。通过点击相应的图标,可以以原始的反汇编、图形、反编译和二进制的形式查看:
右键单击代码对象,可以查看对该对象的引用/来自,甚至更改其名称(在反编译的伪代码中无效):
此外,在中间下方可以编写Python命令。
右侧面板
在右侧面板中,可以看到一些有趣的信息,例如导航历史记录(以便了解如何到达当前情况)、调用图(可以看到调用此函数的所有函数以及此函数调用的所有函数)和局部变量信息。
dtruss
dtruss -c ls #Get syscalls of ls
dtruss -c -p 1000 #get syscalls of PID 1000
ktrace
即使启用了SIP,您仍然可以使用此方法。
ktrace trace -s -S -t c -c ls | grep "ls("
dtrace
它允许用户以极低的级别访问应用程序,并提供了一种追踪程序甚至更改其执行流程的方式。Dtrace使用探针,这些探针分布在内核的各个位置,例如系统调用的开始和结束位置。
DTrace使用**dtrace_probe_create
函数为每个系统调用创建一个探针。这些探针可以在每个系统调用的入口和出口点**触发。与DTrace的交互通过/dev/dtrace进行,该设备仅对root用户可用。
可以使用以下命令获取dtrace的可用探针:
dtrace -l | head
ID PROVIDER MODULE FUNCTION NAME
1 dtrace BEGIN
2 dtrace END
3 dtrace ERROR
43 profile profile-97
44 profile profile-199
探针名称由四个部分组成:提供者、模块、函数和名称(fbt:mach_kernel:ptrace:entry
)。如果您没有指定名称的某个部分,DTrace将将该部分视为通配符。
要配置DTrace以激活探针并指定触发时要执行的操作,我们需要使用D语言。
更详细的解释和更多示例可以在https://illumos.org/books/dtrace/chp-intro.html中找到。
示例
运行man -k dtrace
以列出可用的DTrace脚本。示例:sudo dtruss -n binary
- 在行中
#Count the number of syscalls of each running process
sudo dtrace -n 'syscall:::entry {@[execname] = count()}'
- 脚本
syscall:::entry
/pid == $1/
{
}
#Log every syscall of a PID
sudo dtrace -s script.d 1234
syscall::open:entry
{
printf("%s(%s)", probefunc, copyinstr(arg0));
}
syscall::close:entry
{
printf("%s(%d)\n", probefunc, arg0);
}
#Log files opened and closed by a process
sudo dtrace -s b.d -c "cat /etc/hosts"
syscall:::entry
{
;
}
syscall:::return
{
printf("=%d\n", arg1);
}
#Log sys calls with values
sudo dtrace -s syscalls_info.d -c "cat /etc/hosts"
ProcessMonitor
ProcessMonitor 是一个非常有用的工具,用于检查进程执行的与进程相关的操作(例如,监视进程创建的新进程)。
FileMonitor
FileMonitor 允许监视文件事件(如创建、修改和删除),并提供有关这些事件的详细信息。
Apple Instruments
Apple Instruments 是Xcode开发工具的一部分,用于监视应用程序性能,识别内存泄漏和跟踪文件系统活动。
fs_usage
允许跟踪进程执行的操作:
fs_usage -w -f filesys ls #This tracks filesystem actions of proccess names containing ls
fs_usage -w -f network curl #This tracks network actions
TaskExplorer
Taskexplorer 是一个有用的工具,可以查看二进制文件使用的库,它正在使用的文件以及网络连接。
它还会对二进制进程进行virustotal检查,并显示有关二进制文件的信息。
PT_DENY_ATTACH
在这篇博文中,您可以找到一个关于如何调试正在运行的守护进程的示例,该守护进程使用了**PT_DENY_ATTACH
**来防止调试,即使SIP已禁用。
lldb
lldb 是用于macOS二进制文件调试的事实上的工具。
lldb ./malware.bin
lldb -p 1122
lldb -n malware.bin
lldb -n malware.bin --waitfor
{% hint style="warning" %}
在lldb中,使用process save-core
命令转储进程
{% endhint %}
(lldb) 命令 | 描述 |
---|---|
run (r) | 开始执行,直到遇到断点或进程终止。 |
continue (c) | 继续执行被调试进程。 |
nexti (n / ni) | 执行下一条指令。该命令会跳过函数调用。 |
stepi (s / si) | 执行下一条指令。与nexti命令不同,该命令会进入函数调用。 |
finish (f) | 执行当前函数(“frame”)中剩余的指令,然后返回并停止。 |
control + c | 暂停执行。如果进程已经运行(r)或继续(c),这将导致进程在当前执行位置停止。 |
breakpoint (b) | b main b -[NSDictionary objectForKey:] b 0x0000000100004bd9 br l #断点列表 br e/dis <num> #启用/禁用断点 breakpoint delete <num> |
help | help breakpoint #获取断点命令的帮助 help memory write #获取写入内存的帮助 |
reg | reg read reg read $rax reg write $rip 0x100035cc0 |
x/s <reg/memory address> | 以空字符结尾的字符串形式显示内存。 |
x/i <reg/memory address> | 以汇编指令形式显示内存。 |
x/b <reg/memory address> | 以字节形式显示内存。 |
print object (po) | 这将打印参数引用的对象 po $raw
请注意,大多数苹果的Objective-C API或方法返回对象,因此应通过“print object”(po)命令显示。如果po没有产生有意义的输出,请使用 |
memory | memory read 0x000.... |
disassembly | dis #反汇编当前函数 |
parray | parray 3 (char **)$x1 #检查x1寄存器中的3个组件的数组 |
{% hint style="info" %}
在调用**objc_sendMsg
**函数时,rsi寄存器保存方法的名称,以空字符结尾的(“C”)字符串。要通过lldb打印名称,请执行以下操作:
(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) print (char*)$rsi:
(char *) $1 = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) reg read $rsi: rsi = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
{% endhint %}
反动态分析
虚拟机检测
- 命令**
sysctl hw.model
**在主机为MacOS时返回"Mac",而在虚拟机上返回其他值。 - 通过调整**
hw.logicalcpu
和hw.physicalcpu
**的值,一些恶意软件尝试检测是否为虚拟机。 - 一些恶意软件还可以根据MAC地址(00:50:56)判断机器是否为VMware。
- 还可以使用简单的代码检测进程是否正在被调试:
if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //process being debugged }
- 还可以使用**
ptrace
系统调用以PT_DENY_ATTACH
**标志调用。这可以防止调试器附加和跟踪。 - 您可以检查是否导入了**
sysctl
或ptrace
**函数(但恶意软件可能会动态导入它们) - 如在此文档中所述:“Defeating Anti-Debug Techniques: macOS ptrace variants”:
“消息“Process # exited with status = 45 (0x0000002d)”通常是调试目标使用PT_DENY_ATTACH的明显迹象”
模糊测试
ReportCrash
ReportCrash用于分析崩溃的进程并将崩溃报告保存到磁盘。崩溃报告包含的信息可以帮助开发人员诊断崩溃的原因。
对于在每个用户的launchd上下文中运行的应用程序和其他进程,ReportCrash作为LaunchAgent运行,并将崩溃报告保存在用户的~/Library/Logs/DiagnosticReports/
目录中。
对于守护进程、在系统launchd上下文中运行的其他进程和其他特权进程,ReportCrash作为LaunchDaemon运行,并将崩溃报告保存在系统的/Library/Logs/DiagnosticReports
目录中。
如果您担心崩溃报告被发送到Apple,您可以禁用它们。否则,崩溃报告可以帮助您弄清楚服务器崩溃的原因。
#To disable crash reporting:
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
#To re-enable crash reporting:
launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
睡眠
在进行MacOS模糊测试时,不允许Mac进入睡眠状态非常重要:
- systemsetup -setsleep Never
- pmset,系统偏好设置
- KeepingYouAwake
SSH断开连接
如果您通过SSH连接进行模糊测试,确保会话不会断开非常重要。因此,请更改sshd_config文件:
- TCPKeepAlive Yes
- ClientAliveInterval 0
- ClientAliveCountMax 0
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
内部处理程序
查看以下页面以了解如何找到负责处理指定方案或协议的应用程序:
{% content-ref url="../macos-file-extension-apps.md" %} macos-file-extension-apps.md {% endcontent-ref %}
枚举网络进程
这是一个有趣的方法,可以找到管理网络数据的进程:
dtrace -n 'syscall::recv*:entry { printf("-> %s (pid=%d)", execname, pid); }' >> recv.log
#wait some time
sort -u recv.log > procs.txt
cat procs.txt
或者使用netstat
或lsof
Libgmalloc
{% code overflow="wrap" %}
lldb -o "target create `which some-binary`" -o "settings set target.env-vars DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib" -o "run arg1 arg2" -o "bt" -o "reg read" -o "dis -s \$pc-32 -c 24 -m -F intel" -o "quit"
Fuzzers
AFL++
适用于CLI工具
Litefuzz
它可以与macOS的GUI工具一起使用。请注意,一些macOS应用程序具有特定要求,例如唯一的文件名、正确的扩展名,需要从沙盒(~/Library/Containers/com.apple.Safari/Data
)中读取文件...
一些示例:
{% code overflow="wrap" %}
# iBooks
litefuzz -l -c "/System/Applications/Books.app/Contents/MacOS/Books FUZZ" -i files/epub -o crashes/ibooks -t /Users/test/Library/Containers/com.apple.iBooksX/Data/tmp -x 10 -n 100000 -ez
# -l : Local
# -c : cmdline with FUZZ word (if not stdin is used)
# -i : input directory or file
# -o : Dir to output crashes
# -t : Dir to output runtime fuzzing artifacts
# -x : Tmeout for the run (default is 1)
# -n : Num of fuzzing iterations (default is 1)
# -e : enable second round fuzzing where any crashes found are reused as inputs
# -z : enable malloc debug helpers
# Font Book
litefuzz -l -c "/System/Applications/Font Book.app/Contents/MacOS/Font Book FUZZ" -i input/fonts -o crashes/font-book -x 2 -n 500000 -ez
# smbutil (using pcap capture)
litefuzz -lk -c "smbutil view smb://localhost:4455" -a tcp://localhost:4455 -i input/mac-smb-resp -p -n 100000 -z
# screensharingd (using pcap capture)
litefuzz -s -a tcp://localhost:5900 -i input/screenshared-session --reportcrash screensharingd -p -n 100000
更多关于Fuzzing MacOS的信息
- https://www.youtube.com/watch?v=T5xfL9tEg44
- https://github.com/bnagy/slides/blob/master/OSXScale.pdf
- https://github.com/bnagy/francis/tree/master/exploitaben
- https://github.com/ant4g0nist/crashwrangler
参考资料
☁️ HackTricks云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一家网络安全公司工作吗?想要在HackTricks中宣传你的公司吗?或者想要获取PEASS的最新版本或下载PDF格式的HackTricks吗?请查看订阅计划!
- 发现我们的独家NFT收藏品——The PEASS Family
- 获得官方PEASS和HackTricks周边产品
- 加入💬 Discord群组 或 Telegram群组 或 关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享你的黑客技巧。