本文将分析的样本是OSX.TinyShell的变种:TinyTim。早在2018年,我就发现有攻击者正在使用Tiny SHell的改良版。这个后门(Tiny SHell,是开放源码的)的运行方式类似于SSH的可疑版本。虽然我已经有一段时间没有遇到新的示例了,但是我完全相信攻击者仍然在使用它。

目前,尚未有专门的文章讨论讨论有关该恶意软件的技术细节。这可能是因为实际上,它相对于其开源形式几乎没有什么变化,但是这些修改的确使我们能够通过多种方式检测其独特性。由于该恶意软件已被恶意行为者修改,因此称其为Tiny SHell似乎并不准确。因此,我将这个特定的修改版本称为“TinyTim”(因为我开始尝试在假期前后撰写此博客文章,并将发布拖到现在为止)。

本文中使用的样本可以在VirusTotal上找到(SHA256:8029e7b12742d67fe13fcd53953e6b03ca4fa09b1d5755f8f8289eac08366efc)。

在VirusTotal页面上,你会注意到许多反病毒扫描程序将其标记为OSX.Keydnap,但我不知道这种联系是如何产生的,因为我看不到它们之间的共同点。

发现过程

第一次观察表明,这个恶意软件是由开发人员签名的。我不知道这是一个合法的被盗的签名证书,还是它是由攻击者创建和拥有的。这很有趣,因为恶意软件通常仅用于攻击Gatekeeper的签名。正如我之前发现的那样,这个恶意软件是通过SSH使用受攻击的凭证在受害系统上释放的。也许攻击者是有意使用带符号的二进制代码来进行混合(因为macOS上的大多数二进制代码都是带符号的)。使用macOS的代码签名实用程序,我们可以转储恶意软件的代码签名信息:

如上所述,我们今天看到的这种变体是直接基于开源Tiny SHell后门的。Tiny SHell源代码进行的主要更改之一是添加了一个称为MyDecode的函数,攻击者使用此函数对二进制文件内的某些“敏感”字符串进行编码。如果我们想对这里发生的事情有个更好的了解,就必须在Hopper等反汇编程序中打开它。

在main函数内部,第一个检查显示TinyTim添加了一些基本的反调试函数。在开始时,我们看到ptrace与ptrace_deny_attach参数一起使用,如果程序在附加到调试器时执行,ptrace_deny_attach参数将立即关闭程序,我们必须记住这一点。

在检查调试器是否存在之后,它调用getuid,它返回执行程序的用户的用户ID。在这种情况下,恶意软件会检查根用户的UID是否为0。在这两种情况下,MyDecode函数最终运行在一个看起来像是乱码的字符串上。如果我们在左边的标签中选择_MyDecode并按下x,则可以很好地看到引用此函数的所有位置:

main调用11个,tshd_runshell调用2个,显然,这个恶意软件经常依赖于这个函数。如果我们把Hopper视图切换到伪代码,我们会看到此函数实际上是非常基本的:

这里要重点关注的关键项是r14 ^ r15,这是恶意软件常见的两个字节的简单XOR运算。我们看到r14和r15的值是传递给该函数的第二个和第三个参数的值。此处传递的第一个参数是攻击者想要取消屏蔽的字符串。如果回到主代码,我们可以看一下攻击者调用MyDecode时传递的值:

在前几个调用中,我们看到MyDecode使用XOR模式0x4 ^ 0x2对每个字符串进行解码。我们有一些选项可以将这些字符串转换回可读的文本。我们可以调试程序,也可以编写简单的脚本为我们解码字符串。或者,我们可以同时做!让我们从调试开始。

准备调试

在开始之前,我们必须采取以下步骤来准备这个可执行文件,以便它能够运行。

1. 通过chmod + x赋予TinyTim可执行文件权限;

2. 使用以下代码删除已撤销的签名:codesign --remove-signature;

3. 使用xattr -d com.apple.quarantine删除隔离位(假设已下载此恶意软件);

4. 删除前面讨论的ptrace调用,这是一种防调试技术,如果检测到调试器,它将关闭该程序。我们可以通过在ptrace调用上放置一个断点,然后跳过它来完成此操作,或者我们可以简单地NOP它,因此我们不必每次运行时都担心一个额外的断点。

攻击过程

现在,我们已经完成了所有的设置,我们可以在调试器中打开TinyTim并开始使用MyDecode函数。让我们在函数末尾的返回处放一个断点,然后启动调试器:

当在调试器中命中断点时,这意味着MyDecode函数刚刚完成运行。如果使用x / s $ rdx命令打印RDX寄存器,我们可以看到已解码的字符串:

在本例中,我们看到已解码的字符串是“/Users/%@/Library/Fonts/.cache”。请记住,我们是以基本用户的身份运行的,从我们在main中看到的情况来看,如果它作为根用户运行,将使用不同的路径(请参见第一个屏幕快照中的if/else语句)。我们可以继续“跳转到下一个断点”并打印每个字符串。结果并不令人惊讶:

0x10000c260: “/Users/%@/Library/Fonts/.cache”

0x7ffeefbffa40: “PROG_INFO”

0x7ffeefbffa50: “name_masq”

0x7ffeefbffa60: “CONN_INFO”

0x7ffeefbffb28: “domain”

0x7ffeefbffa70: “”

0x7ffeefbffa70: “next_time”

大多数安全分析人员都将上述字符串视为后门配置选项,这些选项可能是从“/Users/%@/Library/Fonts/.cache”文件中读取了这些选项。但是,由于没有在指定位置创建配置文件,因此没有成功读取这些配置。还要注意,其中一个已解码的字符串是空的。这有点奇怪,但我们稍后会再讨论它。让我们一起整理一些快速的python代码,这些代码也可以解开这些字符串,因为这样做不会造成任何攻击性。这没有什么复杂的,我们只需要遍历提供的字符串中的每个字符,并在其上运行XOR方案来获得已解码的字符。

现在我们无需使用调试器就可以轻松解码:

太棒了!我们现在可以获取存储在可执行文件中的各种字符串,并以纯文本的形式查看它们。继续,我们可以尝试创建一个配置文件来查看发生了什么,但是我们不知道配置文件的格式,接下来看看是否可以解决这个问题。

发现配置格式的关键实际上是在getProfileString函数中,该函数仅引用fopen,fgets,fseek和fclose函数。这些函数通常用于打开、关闭和移动文件的不同内容。

我们可以看到fopen打开了指定为arg0的文件,在本例中,arg0是恶意软件的配置文件。然后开始解析它。在文件的底部,我们看到sscanf正在使用某些特定的格式:

你可以使用sscanf函数在网上找一下,或者你可以使用我们应该已经使用过的方法,即使用GetProfileString函数,它可以准确地揭示我们所要查找的内容。

这里我们有一个函数,它是来自Windows的某种类型的端口,允许用户读取ini格式的配置文件。如果考虑一下我们前面看到的MyDecode函数的值,这是有意义的。这意味着所有大写的项都是lpAppName值,小写的项是lpKeyName值。当然,这在Mac上感觉有点不自然,因为这是Windows ini格式的一部分,但实际上它只是一个文本文件,这真的是一种格式吗?这意味着我们的配置文件应该如下:

这里使用的值当然是为我自己的测试而设置的,但是这种格式应该可以达到目的。一种简单的确认方法是在getProfileString底部附近的strcpy函数上放置一个断点,因为这个函数可能用于保存从配置文件中取出的字符串。一旦断点被命中,我们就可以使用x/s $RDI打印RDI寄存器(当函数被调用时,RDI应该总是保持arg0)来显示传递给strcpy函数的第一个参数,然后继续到下一个断点并重复。

使用正确的配置文件格式之后,我们将更接近于可操作的恶意软件。然而,仍有一些悬而未决的问题。让我们重新检查放置在myDecode函数上的断点,然后再次打印出每个解码后的值。你还记得吗,我们尝试打印的第六个字符串是空字符串,让我们看看是否有任何变化?

现在,解码后的字符串显示为749060607。请注意,该字符串在域字符串解码后立即解码。只需看一下就可以看出它与我们提供的localhost IP地址的长度相同-127.0.0.1。

如果我们使用我们编写的myDecode.py脚本并在127.0.0.1上运行它,那么我们是否可能得到749060607?

事实证明,我们在配置文件中使用的IP地址必须使用XOR方案进行编码。这对于攻击者而言是明智的。这样可以确保即使找到配置文件,也无法以纯文本方式找到命令和控制IP或域。如果他们使用的是已知的恶意IP地址,这还可以确保通过简单的YARA规则无法提取他们使用的C2。因此,如果我们希望看到与该恶意软件的成功连接,则必须确保首先对存储在配置文件中的IP或域进行了相应的编码。由于XOR是可逆的,并且我们已经知道所使用的方案,因此最终变得非常简单。我们可以通过在python myDecode脚本中翻转单个运算符来实现:

它以所需的掩码格式提供了127.0.0.1,可以在我们更新配置文件后正确解码:

现在你可能认为我们已经准备好连接回C2服务器了,然而,TinyTim还有另一个反调试技巧。如果我们再看一下伪代码中的main函数,我们会注意到connect函数的调用依赖于一个非匹配的字符串比较。

让我们在此strcmp函数上添加一个断点,并通过打印寄存器RDI和RSI(传递给strcmp的第一个和第二个参数)来查看正在比较的内容:在连接到指定的C2之前,要进行一次检查,以确保这不是试图连接到运行恶意软件的同一台计算机,这是恶意软件开发者的另一个聪明举动。有很多方法可以绕过这个问题。为了简单起见,我将在VM中启动微型Tiny SHell服务器,获取该VM的本地IP地址,使用XOR模式重新询问IP,并将其添加到配置文件中,这样问题就解决了。运行TinyTim现在将创建到我的VM上的Tiny SHelll服务器的连接,这样最后一个问题就解决了。

TinyTim想要一个密码,这是意料之中的,因为在其开源形式Tiny SHell中,用户需要输入密码。但是,因为我们没有在配置文件中看到指定的密码选项,所以我们知道它必须存储在可执行文件的某个地方。开源的Tiny SHell将该密码称为机密,在Hopper中,我们可以对秘密进行简单的搜索:

现在,我们会看到一个XREF指向一个有趣的字符串' lcc,./3,我们可以尝试使用此密码作为密码,但是与可执行文件中的其他所有字符串一样,实际上已经对其进行了编码,这很有可能会有所帮助。因此,我们将首先使用python脚本对其进行解码:

一直以来,我们的目标都是让恶意软件连接到我们的C2服务器,以查看是否可以通过任何方式对其进行进一步修改。事实证明,从此以后,这种恶意软件的行为就像开源的Tiny SHell。因此,主要的增加是编码字符串,增加了用于快速更改的配置文件以及少量的反调试技术。与其继续使用我们的反编译器,不如仅仅看一下Tiny SHell客户端源代码就更有意义了。

参考及来源:https://objective-see.com/blog/blog_0x58.html

macos无法验证此app不包含恶意软件_macOS 平台的一款后门样本(TinyTim)的分析相关推荐

  1. macOS无法验证此App不包含恶意软件。

    当在 macOS 上尝试打开从网页上下载的软件 texstudio 时,出现了错误, 无法打开"texstudio",因为无法验证开发者. macOS无法验证此App不包含恶意软件 ...

  2. 【Mac】macOS无法验证此App不包含恶意软件 解决方法

    解决方法 Mac电脑打开app,提示无法验证此App不包含恶意软件解决方法

  3. 「macOS无法验证此APP不包含恶意软件」的处理方式

    场景 解决方案 1.不要动上面那个窗口,进入设置-安全性与隐私-通用,点击「仍要打开」 注意:如果没有「仍要打开」,需要按住control打开APP  2.之前的窗口点击「取消」 3.再次重新打开AP ...

  4. macOS 无法验证此App不包含恶意软件

    具体命令如下 sudo xattr -rd com.apple.quarantine /Applications/Compressor.app (应用名称) Password: 转载: http:// ...

  5. macOS无法验证此App不包含恶意软件

    换了iMac,刚用有点不习惯,特别是它这安全机制,比ubuntu高太多... 想用android ndk进行交叉编译,里面的很多那种可执行文件,会弹出如下错误 解决办法: 1.点取消 2.打开系统偏好 ...

  6. 解决macOS Catalina(10.15)解决阻止程序运行“macOS无法验证此App不包含恶意软件”

    在终端里面输入如下命令 sudo spctl --master-disable 下面图片对比执行命令前后,安全性与隐私 界面上显示的差异: 使用命令之后,界面变了

  7. 网上下载软件,macOS无法验证此App不包含恶意软件。

    博主一般常用第一种: 1.解决方法一:按住Control键点按应用, 然后打开,这样会把应用增加到白名单中许可执行. 2.解决方法二:打开系统偏好设置>安全性与隐私>通用,这个时候有个按钮 ...

  8. mac:彻底解决-安装应用后提示:无法打开“XXX”,因为无法验证开发者的问题;无法验证此App不包含恶意软件

    mac从浏览器或其他电脑接收了应用,但是打开报错 目录 报错 解决办法 一次性方法 永久解决方法 验证 恢复应用验证 报错 截图如下: 错误信息 无法打开"XXX",因为无法验证开 ...

  9. Mac电脑打开app,提示无法验证此App不包含恶意软件解决方法

    在mac系统中安装自己下载的软件,经常会提示"无法打开,因为apple无法检查其是否包含恶意软件"无法使用,下面我们就来学习一下怎么解决这个问题. 解决方法一:(这个亲测可行,其他 ...

最新文章

  1. python 空对象模式_Python 单例模式(3种方式)
  2. linux个人常用命令备注
  3. 【Python教程】dict字典的使用方法
  4. 重试次数配置_TestNG实践——2.用例失败重试
  5. 快速排序算法javascript实现
  6. python canvas画移动物体_如何实现Canvas图像的拖拽、点击等操作
  7. windows php5.3升级,Windows10系统将PHPNOW升级PHP版本为5.3.5
  8. SQL Server AlwaysOn集群在辅助副本创建只读账号
  9. 【CCS2018】SDN跨应用中毒攻击
  10. FileReader详解与实例---读取并显示图像文件 | JS Mix
  11. 圣思园java se培训总结(58-)(java1.5新特性,可变参数,包装类)
  12. 量化感知训练_一文速览EMNLP 2020中的Transformer量化论文
  13. CIO:节省IT部门开支十招
  14. 解决jsp页面数据传递乱码问题
  15. VLAN Mapping实现同一网段不同VLAN的主机通信
  16. Altium designer学习(二)pcb库不求人——立创商城导出封装库
  17. 《佛祖都说了些什么》读书笔记
  18. 双稳态电路的两个稳定状态是什么_干货|常见的脉冲电路到底有何用途和特点?终于了解了!...
  19. 设计100倍同向放大电路
  20. 七年级认识计算机软件教案,七年级信息技术第三单元 第一节认识计算机网络教案.doc...

热门文章

  1. 全新防火墙6.0 单条PPPOE(ADSL)上网配置
  2. Mysql数据库drop表不用跑路,表空间传输助你恢复数据
  3. CentOS 6.8下ELK+filebeat+redis 日志分析平台
  4. 实战 | F1060路由模式典型组网配置案例(静态路由)
  5. vue弹窗调用另一个弹窗_电脑桌面“脏乱差”,插件弹窗广告一个不少,学会say no很重要...
  6. Maven错误:“No goals have been specified for this build...”问题解决
  7. 解决vi/vim中粘贴会在行首多很多缩进和空格的问题
  8. 【C语言】利用递归解决猴子吃桃问题
  9. 【虚拟机ubuntu设置ssh】ssh连不上问题解决方法
  10. 使用idea进行Maven打包异常:Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war