macOS安全更新第2部分:在APPLE的MRT APP上运行DIFFS
Posted 嘶吼专业版
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了macOS安全更新第2部分:在APPLE的MRT APP上运行DIFFS相关的知识,希望对你有一定的参考价值。
在本系列的中,我们介绍了如何在Apple对其内置安全工具进行更改时保持最新运行状态。在本文中,我们将首先研究如何提取数据并在Apple的恶意软件删除工具(也称为MRT.app)上运行差异。你唯一需要执行此操作的工具是Apple的免费Xcode命令行工具。
为什么“字符串”工具无法显示所有字符串
在中,我描述了如何在MRT.app的二进制文件上运行字符串工具,以及如何使用反汇编程序搜索和解码隐藏在字节数组中的其他字符串。但是,这种方法存在两个问题。幸运的是,有一种更好的方法,它既快速又不需要手工操作。
重要的是,这些十六进制数字是ASCII字符,你可以通过在控件中单击并选择“字符”,在Hopper中显示它们。
这是一个字符数组,可以将它们连接起来形成一个字符串。当包含该数组的特定函数在内存中执行时,将创建字符串“ EliteKeyloggerAccessibilityStatus”。
为了比较起见,r2中的设置也相同,默认情况下,r2会很好地呈现ASCII,然后在Hopper中呈现。
让我们暂时保留灰色列中的操作码,因为在尝试自动提取这些字符串时,它们很有用。你会注意到,所有的行都以C6开头,除第一行之外的所有行均以40结尾。字节C6是Intel汇编指令,告诉处理器将一些值移至RAX累加器寄存器,下面的指令就是将“将十六进制数45移到RAX中”。
C6 00 45
C6 40 01 45
C6 40 02 6C
C6 40 03 69
C6 40 09 6F
我们只需要注意另一个操作码,那就是当一个进程(又名“函数”)返回C3时的操作码。
提取隐藏在字节数组中的字符串
如果你已经安装了Xcode命令行工具,我们可以通过其他提供的实用程序使用otool和一些重管道一次性转储字节数组中包含的所有字符串。对于那些渴望尝试一下的人,可以试试这个命令,然后我们将详细解释它的工作原理,做一些调整并建议将其保存为脚本。
如果你在Catalina上,请尝试以下操作:
otool -tvj /Library/Apple/System/Library/CoreServices/MRT.app/Contents/MacOS/MRT | grep movb | grep \(%rax\)$ | awk '{ print(NF==7)?"0x0a"$(NF-1):$(NF-1) }' | sed 's/\$//g' | grep -v % | sed 's/{0x,\,}//g' | grep -v '-' | awk 'length($0)>1' | awk 'length($0)!=3' | xxd -r -p
对于Mojave和更早的版本:
otool -tvj /System/Library/CoreServices/MRT.app/Contents/MacOS/MRT| grep movb | grep \(%rax\)$ | awk '{ print(NF==7)?"0x0a"$(NF-1):$(NF-1) }' | sed 's/\$//g' | grep -v % | sed 's/{0x,\,}//g' | grep -v '-' | awk 'length($0)>1' | awk 'length($0)!=3' | xxd -r -p
但是,如果一切顺利,你应该获得类似于下图的输出结果。我正在运行Mojave,因此我使用了上面两个代码块中的第二个(如果遇到错误,请检查你使用的macOS版本代码是否正确)。
在当前版本的MRT.app(在撰写本文时为v1.52)上,如果我重复该命令(向上箭头以调出最后一个命令,对于那些不是常规命令行用户的用户)并附加| wc –l。获取行数,返回169行。
首先,otool -tvj本质上产生的输出类似于在Hopper和r2中看到的输出,但是格式略有不同。如果我们在终端中单独运行它,并使用上一节中学到的方法为它提供了MRT二进制文件的路径,,使用我们在上一节学到的知识,我们可以很容易地手动找到字节数组,只需搜索c6 4001(这将使我们得到索引1;请记住,数组的开头是从索引0处开始的。
请注意,otool使用助记符movb,而不是仅使用mov,这使其更加透明。因此,转储反汇编后的第一个grep是提出包含movb指令的每一行。其次,字节数组中的每一行都将以(%rax)结尾,这就是我们的第二个grep。
回想一下,每个数组都以C6 00 XX开头。由于无需添加索引来存储第一个字符,因此指令中只有三个字节;相反,数组中的其余所有行都有四行(如果不清楚原因,请查看上一节)。因此,我们现在使用awk和三元运算符来测试该行中有多少列。
如果该行正好有7列,我们知道这可能是字节数组的开始,因此我们在输出前添加0x0a(换行符),然后打印该字符的ASCII码(在0a之前将产生新行)输出中的每个解码字符串)都位于倒数第二列(NF -1)中。如果该行具有多于或少于7列,则我们输出倒数第二列(NF -1)中的所有内容,大多数情况下(请参见下文)将使用模式“ 0xXX”为我们提供值。
此时,每行都通过几个grep,sed和awk命令进行管道传输,以删除除实际删除的十六进制数之外的所有内容。我们还排除了仅输出1或3长度的行,因为在下一个和最后一个阶段,我们的十六进制输出需要被二整除。
最后一步涉及将输出传递到xxd并使用-r和-p开关(你也可以使用rax2 -s替代radd2风扇的xxd -r -p!)将十六进制编码的ASCII转换为人类可读的语言。该进程要求每个有效的十六进制数字都必须具有两个字符(XX)的长度才能生成一个可打印的ASCII字符(因此,请勿将长度为1或3的任何内容管道输送到其中,否则你将收到一些错误的输出!) 。
如果你只想了解MRT的新功能,那么我们的脚本应该和进行差异化一样好,但对于其他用途,则需要进行调整。特别是,对于攻击的提前预防,在一次检测中查看哪些字符串属于同一类将很有用。这可能有助于我们在VirusTotal之类的公共恶意软件存储库中或从端点收集的我们自己的数据中查找样本。
在上一节的末尾,我指出“进程结束”指令的操作码为C3。现在,我们可以使用它用一些名义上的定界符来划分字符串组。这是上面提供的提取代码的一个版本,但是在不同功能的字符串之间插入定界符(请注意,粘贴此代码时,你需要用实际路径替换MRT二进制文件):
otool -tvj | egrep 'movb|retq' | egrep '\(%rax\)$|retq' | awk '{ print(NF==7)?"0x0a"$(NF-1):$(NF-1) }' | sed 's/^c3/5c/' | sed 's/\$//g' | grep -v % | sed 's/{0x,\,}//g' | grep -v '-' | awk 'length($0)>1' | awk 'length($0)!=3' | xxd -r -p
如你所见,主要区别在于我们现在为包含助记符retq的行添加了grep(同样,请注意otool和Hopper之间的区别)。稍后,在执行第一批awk命令之后,我们将操作码c3替换为5c,它代表反斜杠字符。在反汇编中,当我们遇到这条指令时,该指令实际上将位于列NF-1处,因此先前的管道已经捕获了该指令。现在,整个命令的结果有助于我们直观地看到一个进程中包含的字符串与另一个进程中包含的字符串之间的差异。
请注意,由于c3的grep和sed搜索和替换非常粗糙,因此有时来自不同函数的字符串之间只会出现一个正斜杠,有时还会出现多个斜杠。因此,有一个更一致的“程序结束”标记会很好。第二,我们最好将这些替代版本(Mojave,Catalina,显示/隐藏“进程结束”标记)放入带参数的脚本中。不过此处不是进行常规bash脚本编写的地方,我们的空间已经用完了。
在MRT.app上运行差异
为了进行比较,你将需要两个版本的MRT二进制文件,因此我建议现在将当前版本复制到专用文件夹中以进行此类工作,以便在下一次迭代到来时将旧版本安全地塞入进行测试。对于版本1.51、1.52等,我使用一个简单的命名法MRT_151,MRT_152。
$ cp /System/Library/CoreServices/MRT.app/Contents/MacOS/MRT ~//MRT_152
注意:对于Catalina,请记住在/ Library / Apple之前添加该路径。
通过上面的讨论,我们现在可以在MRT.app可执行文件上运行两种字符串差异:带字符串或FLOSS的普通字符串,以及使用上述代码,我称之为“ byteStrings”命令或脚本的字符串。
除了字符串外,还应该知道machO二进制文件中更改了哪些类,可能从库中导入了哪些新符号等。内置工具nm和otool有一些有用的选项。我也倾向于大量使用rabin2(r2工具集的一部分)进行二进制分析,如下面的一些示例所示。
为了对两个MRT二进制文件进行快速差异处理,我们可以利用称为进程替换的Shell函数,该函数允许我们将命令的结果视为文件,然后将其通过管道传递至差异实用程序。
使用语法如下:
$ diff -y <([commands] path to older file) <([commands] path to newer file)
-y开关允许我们并排查看diff,以方便使用。进程替换发生在<()内部。
让我们尝试一下以下语法:
$ diff -y <(strings -a MRT_151) <(strings -a MRT_152)
每行有三个可能的结果,显示在两列之间。>表示右边的条目已添加到较新文件中的该位置;<表示较新文件中该位置左侧的条目丢失,而|表示该位置的行已更改。
但是,在实践中,会出现代码重构,如上图所示。请注意,与MRT v151(左侧)相比,MRT v152(右侧)中的pathWithComponents,它的行移动了。
通常,有两种方法可以解决此问题。如果输出不足,通常会进行手动检查。如果有很多输出,则可以通过grepping告诉你要查找的内容,但是你会发现更容易操纵文本文件中的结果。以下两个命令将添加内容和省略内容分别分类为两个单独的文本文件,分别为"added.txt" 和 "missing.txt"。
$ diff added.txt
$ diff <(strings -a MRT_151) missing.txt
sed命令用于删除“大于”和“小于”符号,我们需要这样做,以便我们可以将这两个文件相互区分:
$ diff missing.txt added.txt | grep \> | sort -u
除了字符串之外,要查看的另一个重要更改是类名。我最喜欢的类转储工具是rabin2。我们将使用-cc选项,并grep删除添加项和省略项,再次充分利用流程替换。
$ diff -y <(rabin2 -cc MRT_151) <(rabin2 -cc MRT_152) | egrep ''
你也可以以相同的模式使用其他rabin2选项,例如-l而不是-cc来对链接库进行差异(在本案例中,MRT v1.51和MRT v.152之间没有变化)。同样,使用进程替换将两个二进制文件与nm进行差异有时也会引起微妙的变化。
最后,当然,不要忘了使用我们新的byteStrings工具进行并排比较!
$ diff -y <(./byteStrings MRT_151) <(./byteStrings MRT_152)
总结
在本文中,我们研究了使用不同工具运行差异的方法,这些工具可以帮助我们了解从一个程序版本到另一个版本的变化。在此期间,我们了解了反汇编的基础知识,以了解如何创建自己的工具来自动化流程。
当然,Apple可能会决定选择另一种方法来混淆MRT.app的某些字符串,然后我们将不得不寻找另一种方法来对其进行解码。
本文参考自:https://www.sentinelone.com/blog/macos-security-updates-part-2-running-diffs-on-apples-mrt-app/
以上是关于macOS安全更新第2部分:在APPLE的MRT APP上运行DIFFS的主要内容,如果未能解决你的问题,请参考以下文章
Apple 发布 macOS Big sur 第三个开发者预览版
Apple推出适用于macOS的Safari 14作为独立更新