背景知识介绍

2019年1月,美国国家安全局(NSA)宣布,它将免费向公众开放其逆向工程工具GHIDRA,源码已经于今年3月登陆代码托管平台GitHub 。NSA指出,GHIDRA框架的本质,是一款适用于 Windows、Mac 和 Linux平台的反汇编程序。它能够将可执行文件分解为汇编代码,以进行分析。对于希望深入了解恶意软件,以查看其工作原理的安全研究人员来说,反汇编工具是相当实用的。实际上,NSA早已向其它政府机构分享过该工具。2017年的时候,维基解密在Vault 7中首次曝光了GHIDRA,消息来自于中央情报局(CIA)的内部文件。

用过Tytera MD380对讲机的朋友很多,其较高的性价比让大家轻松无压力的从纯模拟电台跨步到了DMR数字时代,从而感受到DMR技术的魅力。

不过几年前,我们就升级了这个对讲机的固件了,并对其进行了逆向工程。为此我们专门构建了md380tools项目,以便通过其他功能例如全局用户目录,混杂模式和其他USB功能升级固件的功能。

所谓的混杂模式(Promiscuous Mode)是指一台机器能够接收所有经过它的数据流,而不论其目的地址是否是他。它是相对于通常模式(又称“非混杂模式”)而言的。这被网络管理员使用来诊断网络问题,但是也被无认证的想偷听网络通信(其可能包括密码和其它敏感的信息)的人利用。

以下,我会向你详细介绍如何将MD380对讲机固件加载到GHIDRA,然后从md380tools逆向工程项目中导入符号。

配置介绍

首先,你应该拥有MD380Tools源代码,将其进行编译以生成中间文件,例如符号和解密的固件映像。如果你还没有嵌入式ARM开发工具链,请参阅以下内容。

% git clone https://github.com/travisgoodspeed/md380tools
% cd md380tools
% make release

加载固件

GHIDRA似乎在设计时考虑了固件,并且它很乐意支持加载原始二进制文件。

让我们从File/New项目开始,创建一个新的非共享项目。

打开项目后,加载md380tools / firmware / unwrapped / D013.020.img或任何其他未封装的固件映像,这些脚本是由Makefile脚本通过互联网上加密不良的固件中更新生成的。

我们必须将语言设置为little-endian ARM Cortex (ARM:LE:32:Cortex),并使用选项窗口设置正确的加载地址。这些映像包含从48k引导加载程序开始的闪存,因此我们需要加载地址0x0800C000。

1.png

2.png

加载映像后,我们现在将Flash加载到正确的地址,但是我们没有RAM,也没有IO和函数符号。让我们首先使用自动分析器找到函数入口点,然后导入它们的专有名称。

初步分析

当你在加载后首次双击D013.020.img映像时,GHIDRA将提示你运行具有任意数量默认选项的自动分析器。选择默认选项后,再等待一分钟,你将发现数百个函数被准确的标识出来。

不幸的是,并不是所有的内容都能立即被识别出来。例如,位于开头(0x0800C000)的表是中断向量表,但它不位于默认地址。 GHIDRA非常聪明,能够识别其中的许多条目。但有一些例外,比如应用程序自己的代码从未调用的初始堆栈地址(0x0800C000)和重置向量(0x0800C004)。为了了解自动分析器是如何失败的,有必要研究其中的一些问题,但是在本教程中我不会关注它们。

与IDA Pro(一个静态反编译软件)和Binary Ninja(一个逆向平台)不同,GHIDRA的语言设置概念允许它提前知道这个二进制文件完全是Thumb2,没有经典的ARM指令,也不需要设置虚拟寄存器。

在继续从MD380Tools项目中导入其他构件之前,让我们先看一下一些简单的函数,并使用它们来查找其他函数。

让我们从SPI Flash驱动程序的最低级别开始。SPI Flash是一个外部闪存芯片,包含对讲机的代码插头、定义频率和配置设置。在逆向工程中,观察它们如何从SPI Flash芯片中读取设置是非常有帮助的。

首先导航到0x080314bd处的md380_spi_sendrecv函数。通过在反汇编视图中按G来执行此操作,然后向GHIDRA提供地址,它将四舍五入到0x080314bc。在内部,ARM具有所有Thumb函数的奇数地址,但GHIDRA不遵循此约定。之后,选择函数的名称并按F键编辑函数定义,将名称更改为md380_spi_sendrecv。我们可以把这个函数想象成getchar()和putchar(char)封装成的一个函数。它会从SPI漏洞中发送一个字节,同时返回相应的字节。

接下来,导航到0x080314bd并查看其反编译视图。你可以看到,这会发送字节0x03,然后是第二个参数的三个字节。以最重要的开始,然后再是第一个参数指向的所有字节,用于第三个参数的计数。

void FUN_080314bc(undefined *puParm1,uint uParm2,short sParm3)

{
  undefined uVar1;  
  FUN_0803152a();  md380_spi_sendrecv(3);  md380_spi_sendrecv(uParm2 >> 0x10 & 0xff);  md380_spi_sendrecv(uParm2 >> 8 & 0xff);  md380_spi_sendrecv(uParm2 & 0xff);  while( true ) {    if (sParm3 == 0) break;
    uVar1 = md380_spi_sendrecv(0xa5);
    *puParm1 = uVar1;
    puParm1 = puParm1 + 1;    sParm3 = sParm3 + -1;
  }  FUN_08031546();  return;
}

从SPI Flash的数据表中,我们知道0x03是从芯片读取数据字节的命令。这个函数的真实名称是md380_spiflash_read,跟踪它读取的地址允许我们将固件中的函数与其在codeplug中的含义匹配起来。由于我们知道必须在读取之前选择芯片,然后在读取之后取消选择,所以我们可以猜测FUN_0803152a实际上是md380_spiflash_enable而FUN_8031546实际上是md380_spiflash_disable,甚至不需要读取它们的代码。

4.png

使用反编译视图中的L键来定义参数、函数和变量名称,我们可以在去除反编译后得到很多有用的东西,进行很多清理反编译。你可以使用;注释标记。

void md380_spiflash_read(undefined *buffer,uint adr,short length)

{
  undefined currbyte;  
  md380_spiflash_enable();                    /* 0x03 = READ DATA BYTES command */
  md380_spi_sendrecv(3);  md380_spi_sendrecv(adr >> 0x10 & 0xff);  md380_spi_sendrecv(adr >> 8 & 0xff);  md380_spi_sendrecv(adr & 0xff);  while( true ) {    if (length == 0) break;
    currbyte = md380_spi_sendrecv(0xa5);
    *buffer = currbyte;
    buffer = buffer + 1;
    length = length + -1;
  }  md380_spiflash_disable();  return;
}

通过这些方法,我们就能找到相关的功能。在反汇编视图中右键单击函数名称,然后选择“显示引用”以显示函数的每个调用者。在md380_spiflash_enable()上使用Ctrl + Shift + F执行此操作,我们可以得到六个与SPI Flash交互的函数,例如md380_spiflash_write(),md380_spiflash_sektor_erase4k()和md380_spiflash_block_erase64k()。对md380_spiflash_read()执行此操作将为我们提供从SPI Flash中读取的每个函数,并且从这些地址中我们可以知道它们正在读取什么。

例如,考虑这个从0x2040读取20个字节的未知函数。

undefined4 FUN_080226c0(void)

{
  undefined4 unaff_r7;  
  md380_spiflash_read(DAT_08023398,0x2040,0x14);  return unaff_r7;
}

在md380tools/chirp/md380.py的不完整CHIRP驱动程序中,我们看到0x2000是一个配置结构,包含两个用于启动文本的二十字节字符串。这个神秘函数是Get_Welcome_Line1_from_spi_flash,我们可以钩住或修补它来更改在启动时显示的文本!

#seekto 0x2000;
struct {
    u8 unknownff;
    bbcd prog_yr[2];
    bbcd prog_mon;
    bbcd prog_day;
    bbcd prog_hour;
    bbcd prog_min;
    bbcd prog_sec;
    u8 unknownver[4];       //Probably version numbers.
    u8 unknownff2[52];      //Maybe unused?  All FF.
    char line1[20];         //Top line of text at startup.
    char line2[20];         //Bottom line of text at startup.
...

加载RAM的核心转储

现在,我们可以从SPI Flash映像中跟踪这些设置,这听起来很酷。但是如果我们通过查看RAM中的0x08023398来查看其中加载了哪些字节,效果就更好了。为此,我们需要在0x20000000处创建一个128k的区域。STM32F405在0x10000000处也有64k,但链接器很少使用静态缓冲区。

从“文件”菜单中选择“添加到程序”以添加第二个映像。选择md380tools/cores/d13020-core.img,这是一个通过USB从D13.020的启动副本生成的实时RAM转储。在选项窗口中,我们必须将加载地址设置为0x20000000。

8.png

现在我们可以导航到存储字符串的0x2001E3FC。将第一个类型定义为wchar16,然后按[创建一个包含10个元素的数组。在0x2001e410中对第二行执行相同的操作,你可以在SRAM中看到我的对讲机配置的两条启动线!

   2001e3fa 00              ??         00h
        2001e3fb 00              ??         00h
        2001e3fc 4b 00 4b        wchar16[   u"KK4VCZ    "
                 00 34 00 
                 56 00 43 
        2001e410 33 00 31        wchar16[   u"3147092   "
                 00 34 00 
                 37 00 30

修改文字池

最后一个小麻烦是,反编译器对ARM文字池的理解不是很到位。ARM并没有32位的即时信息,相反,它通过在函数之间存在数据池来伪造它们,这些数据池是相对于程序计数器引用的。

此时GHIDRA的逆向进程就会受阻,因为从理论上讲,这些文字池可能会被新的32位值覆盖。由于这种混淆,反编译器表面上会告诉你传递的值是DAT_080233b0,而实际上0x2001E410是0x080233b0处的惟一值。

void Get_Welcome_Line2_from_spi_flash(void){
  md380_spiflash_read(DAT_080233b0,0x2054,0x14);
  return;
}
DAT_080233b0             XREF[1]:     Get_Welcome_Line2_from_spi_flash
080233b0 10 e4 01 20     undefined4 2001E410h

实际上,这种闪存修改起来相当复杂,并且代码不能直接被写入。因此,我们需要告诉反编译器,Flash页面不能在窗口/内存映射中写入。简单地取消复选框并保存新的内存映射将纠正反编译过程,向我们显示正在传递的字符串是“3147092”。当然,我们可以给它一个更清晰的名称,并检查交叉引用,以便了解哪些其他函数使用第二个欢迎行。

11.png

void Get_Welcome_Line2_from_spi_flash(void){
  md380_spiflash_read((char *)u_3147092_2001e410,0x2054,0x14);
  return;
}

从GNU LD加载符号

既然我们已经学会了寻找自己的函数,现在可能是导入其他人已经找到的函数的好时机。

在GHIDRA包含的许多优秀示例脚本中,有一个是ImportSymbolsScript.py,它采用符号名称和地址的平面文本文件在打开的项目中创建标签。

#Imports a file with lines in the form "symbolName 0xADDRESS"
#@category Data
#@author 
 
f = askFile("Give me a file to open", "Go baby go!")

for line in file(f.absolutePath):  # note, cannot use open(), since that is in GhidraScript
    pieces = line.split()
    address = toAddr(long(pieces[1], 16))
    print "creating symbol", pieces[0], "at address", address
    createLabel(address, pieces[0], False)

在md380tools项目中,我们使用Radare2符号来标记我们对映像和GNU LD脚本的看法,以标记我们实际链接的那些部分。使用symbols2ghidra.py <symbols_d03_020> ghidrasyms.txt转换GNU LD脚本非常简单。

14.png

15.png

通过上文,我们可以很容易将MD380固件和符号加载到GHIDRA中,并且反编译器在二进制文件上做了很多复杂的工作。

你还应该注意正确地标记内存页,因为它们是反编译器生成干净、紧凑代码所必需的。处理共享项目的用户,必须确保在更改内存映射或加载新区域之前只签出一个文件。

译者注:经常有用户问该怎么修改文件。其实除了点击菜单栏上的“修改”来修改文件,菜单“版本”里的“签出”也能用来修改文件。

当你要修改文件时,先选中文件,然后点“签出”,文件自动签出并打开后,你修改文件,并保存修改内容。再点“签入”,文件就会保存到多可系统里。

简单说来,该流程就是:签出 -> 修改并保存 -> 签入。

前言

本文我得先从我最近参与的一个安全检测项目开始谈起,本次的客户是一家企业,不得不说,本次我们的客户的安全防护做得非常好。他们的安全运营中心(SOC)配备了很多先进的内部异常检测工具以及顽强的事件响应团队。这里我要说一句,他们是Google的客户,并利用G Suite来处理他们基于云的业务应用程序。

2019年4月,Google为 G Suite带来了一系列更新,本轮更新重点增强了公司数据的保护,既包括控制用户的访问权限,还可以通过提供新的工具来防止网络钓鱼和恶意软件攻击。本次Google还发布了高级网络钓鱼和恶意软件保护Beta版本,旨在帮助管理员保护用户免受恶意附件和电子邮件欺骗等因素的影响。

于是,我花了相当长的时间研究和学习如何破解G Suite并将它们武器化,以下我会详细介绍我使用过的许多不同攻击方法。

对G Suite进行渗透测试时,被Google反制裁。在我和我的团队使用CredSniper(一个使用Python微框架Flask和Jinja2模板编写的网络钓鱼框架)成功地破坏了凭证并绕过了双因素验证之后,我们立即开始横向地在Google应用程序中寻找典型的公司数据。不过,我们碰到了G Suite的异常检测系统,因为它们利用Google Groups向技术团队发送电子邮件,其中就包含有趣的安全警报和crontab命令行日志。不久之后,客户在Google的帮助下发现我们的身份验证活动是可疑的,并触发了一系列内部安全流程。经过努力,我们最终侵入了其他一些账户,此时即使企业有强大的事件响应团队,他们也无法进入我们的OODA循环。后来我们发现,Google的管理API实际上并不是实时的,而且日志延迟了15分钟,这让我们有了足够的攻击信心。为了验证G Suite的强大防御能力,他们联系了Google的SOC寻求帮助。

果然在24小时内,就有安全研究人员一直在跟踪、记录和破坏我们的攻击过程。

在此,我想说的是,客户和Google之间的及时沟通非常重要。然而,有时事情可能会事与愿违,这点我会在下面讲到。

企业和Google之间的联合预防策略的实现

在这24小时内,GoogleSOC能够跟踪和关联我的所有有关此次渗透测试的帐户、电话和API令牌,然后暂停所有帐户。更糟的是,他们还将攻击的指标与我的所有相关账户进行了关联匹配,暂停了我的工作账户。虽然我们的系统管理员第二天重新启用了它,但又被暂停了,同时还暂停了系统管理员重新启用它的权限。由此可见,Google跟踪和关联账户的能力非常非常好。在接下来的几天里,我甚至无法收到Google已经恢复的客户的邮件,且无法访问任何与Google身份验证帐户相关的资源。除此之外,我的工作日程也无法访问。

如果冲突发生在企业账户级别,那么这意味着企业的整个业务可能会戛然而止。在接下来的几周里,我和妻子不断遇到身份验证问题,所有设备(笔记本电脑、电视、恒温器、平板电脑等等)上的Google帐户会话都会随机要求重新身份验证。至此我十分怀疑,我们的家庭IP地址是否在Google系统中被标记为恶意?

如果我的怀疑属实,则意味着一家科技巨头可以主宰我工作和生活的方方面面,想想都可怕,这已经超越了安全行业的范畴。后来,我的客户告诉我,GoogleSOC给他们提供了初始访问向量的链接。

另外,Google是否有关于我的所有关联账户的信息呢? 虽然我的这次渗透测试是违反了Google对渗透测试的要求的规定,但却不违反其云服务条款。显然,每个测试人员在渗透测试时,都需要注意的相关的规定,这是所有测试人员在测试任何基于云的服务时都需要注意的问题。在云服务渗透测试方面,我们还处于空白领域。所以,许多供应商都误认为,即我们永远不会测试他们的核心服务。

解除Google对渗透测试人员的追踪

需要说明的是,我所拥有的每一部智能手机都运行Android系统,我家里几乎所有的智能设备或者都运行Android系统,或者归Google所拥有的,而我本身也是一个G Suite用户。因为我所有的文件都备份到Google云端硬盘,我的Google帐户是我的上网主要帐户,我的所有TOTP 2FA都依赖Google身份验证器,我的电话号码甚至是谷歌语音。毋庸置疑,解除Google对我的追踪是多么迫切。

更换Google移动操作系统

为此我考虑了以下的系统:

1.FireOS(似乎已经停用了);

2.PureOS( ,一款全新的免费Linux发行版);

3.Firefox OS(已经停用了);

4.KaiOS(一个基于Linux的移动操作系统);

5.Ubuntu Touch(不错的选择);

6.LightPhone 2(还没有发布);

7.Windows 10手机版(今年年底发布)

8.Blackberry/SilentPhone/Cryptophone(现在都运行Android)

9.iOS

在对所有可用的选择都测试之后,我最终买了一部iPhone,它与Macbook Pro笔记本电脑结合在一起,彻底改变了我的整个网络生活。

更换2FA验证方案

虽然选择一个TOTP 2FA解决方案相当简单,但是我想再深入一些,并为基于SMS的2FA创建一个完全独立的验证方案。虽然有些人可能认为它与prepper-level status属于同一类别,但它确实为攻击者在攻击备份SMS 2FA实现时创建了额外的保护步骤。有许多TOTP选项,以及使用应用程序集成其他电话号码的VOIP提供商。我没有看到大多数选项之间的太大差异,以下是一些我考虑过的采用TOTP多因子身份验证的应用程序:

Authy ;Authy是一款跨平台的、支持多个设备同时使用的两步验证管理工具,是“Google 身份验证器”的有力替代者。Authy 的优点在于,它可以同时管理多个平台的两步验证,同时支持多设备同时使用,也可以快速在设备之间迁移、抹除,还支持 Touch ID 验证。Authy 可以管理所有使用“Google 身份验证器”的账号系统,包括 Gmail、Evernote、Facebook、Dropbox、LastPass等。Authy 改进了 Google Authenticator 的功能:

Duo Mobile :Duo Mobile 是一款手机系统软件,下载并安装了这款软件后,能够得到Duo网络安全的双因素认证服务,使登录更加安全。

LastPass Authenticator :LastPass新出的验证码应用,支持所以基于时间的一次性密码标准(TOTP)算法的服务。它将双因素验证因子存储在LastPass账号中,可以在不同设备之间云同步。

更换VOIP提供商

Cloud Sim:Cloud SIM技术,其本质上就是聚合全球流量资源,提供跨境场景下的通信服务;

Telos

OpenPhone

Sideline

Line2

更换电子邮件服务商

更换新的邮件提供商时,我遇到了一个很大的问题。我刚开始是希望服务商完全支持别名注册,因为我想为不同的别名创建唯一的电子邮件地址。这听起来可能很疯狂,但使用别名可以方便地整合电子邮件,降低交叉污染的风险。因为我不喜欢我的个人数据被出售,所以我选择了付费电子邮件。现时有多个邮件服务供应商可供选择:

ProtonMail;ProtonMail是知名的安全电子邮件提供商,总部在瑞士,2013年由欧洲核子物理研究所(CERN)、麻省理工(MIT)、以及哈佛(Harvard)的研究人员联合创建,致力于为注重隐私和安全性的用户提供加密电子邮件服务。支持免费和付费两类帐户,所有账户均使用端到端加密功能,默认启用PGP加密。

FastMail;

Office 365;

Zoho;

iCloud;

我使用的电子邮件提供商是FastMail,他们有多个注册方案,你甚至可以自带域名。它内置支持同步联系人和日历,同时支持类似于Google云端硬盘的文件支持。我确实担心我的邮件客户端会在每个电子邮件标题中泄露我的源IP地址,这通常发生在你不使用Webmail客户端时。据悉,FastMail有一个未公开的SMTP端口565,它会从所有出站电子邮件中删除源IP地址。另外,他们也有一个不错的移动应用程序。

脱离Google环境,完全迁移的过程

以下有一些需要注意的事项:

账户方面:

· 使用新的电子邮件地址更新所有网站配置;

· 更新Slack和其他社交应用程序;

· 使用电子邮件作为备份更新其他配置文件;

电话方面:

· 迁移手机文件和图像;

· 在新手机上重新安装应用程序;

数据方面:

· 备份G Suite数据;

· 备份Google云端硬盘文件;

· 导入联系人;

· 导入日历事件;

安全方面:

· 重新同步TOTP 或推送2FA令牌会话;

· 使用SMS 2FA更新配置文件;

帐户迁移

我使用了一些技巧来加速这个过程:首先使用我的密码管理器来跟踪我用新电子邮件地址更新的帐户。这很方便,因为它能帮助我确保覆盖了所有帐户,同时还可以直接更新密码管理器。不过要注意的是,有时密码管理器不会自动更新电子邮件地址。很少有网站不允许我更新我的电子邮件地址。另外,你可能还想考虑重新生成你更新电子邮件地址的帐户所依赖的API令牌。另外,在我更新了我的个人资料电子邮件之后,我使用的API令牌不再有效。

电话迁移

这可能是最简单的迁移了,我把Android手机上的应用程序列了一个简单的清单,并确保在我的新手机上重新安装它们。可惜的是目前还没有一款应用能自动做到这一点。

数据迁移

通过访问https://google.com/takeout,你可以很容易地下载所有帐户数据,但我强烈建议单独同步Google云端硬盘。如果你是一个重度用户,大文件会花费很长的时间。使用Google Takeout的好处是你的所有Gmail都将被下载,唯一的问题是导出我的Google图书时出了问题。由于某种原因,他们不再提供下载或导出功能。

对于存储数据的迁移,我选择用Synology DS218play NAS和Seagate SATA驱动器替换我的家用NAS,然后将所有内容存储在本地而不是云端。我最终购买了两倍的空间并运行了SHR raid配置。这与raid 1配置类似,不同之处在于它是一种自定义Synology raid类型,允许混合和匹配磁盘大小,同时在磁盘发生故障时维护典型的镜像冗余。选择Synology有很多原因,但这个基于Linux的操作系统有一个简化的用户界面,其中包含一些非常酷的内置应用程序,从协作工具到我的Google照片和Google云端硬盘需求的替代品(Moments和Drive应用程序),你甚至可以直接备份Google云端硬盘! 

如果你还想在云中获取更多数据,可以使用以下解决方案:

· AWS S3

· Azure Storage

· Digital Ocean Spaces

· Box.com

· DropBox

注意:不要忘记将你的联系人和日历导入新的提供商。

安全迁移

最后,我们不要忘记GoogleAuthenticator中所有那些讨厌的TOTP令牌会话,以及为所有配置文件更改你的电话号码,这些配置文件仅通过提供SMS来实现2FA解决方案,效果很差。

我非常反对使用基于sms的2FA作为主要的甚至是备份的2FA。如果你的配置文件只启用了SMS 2FA,请确保使用你的新电话号码更新配置文件。

摆脱Google的限制后,重新进入网络环境

现在是删除Google帐户的时候了,因为所有的设置、迁移和正常工作都已经完成。但我没有立即行动,因为我担心我可能遗漏什么内容。结果证明我的选择是正确的,因为在一些情况下,我需要访问我的电子邮件,它被配置为其他配置文件的备份。重新进入网络环境前,要做的事情:

· 删除Google账户

· 出厂重置

对于某些人来说,避免使用Google服务是不可能的。例如,我必须在工作中使用它,那么我如何防止将数据泄露给Google呢?我的做法在一个隔离的环境中,如我的工作笔记本上使用Google。对于互联网搜索,我已经完全使用了DuckDuckGo,DuckDuckGo强调在传统搜寻引擎的基础上引入各大Web 2.0站点的内容,其办站哲学主张维护使用者的隐私权。

《RPC漏洞挖掘案例研究(上)》一文中,我们向你展示了如何使用不同的可用工具和在线资源,在Windows RPC服务器中发现潜在的安全风险(微软通用遥测客户端漏洞)。另外,我们还演示了对RPC服务器进行反向汇编所需的一些基本知识。不过,我们坚信RPC服务器中还有其他潜在的安全漏洞。所以,在本篇文章中,我们将继续研究并改进强化Windows RPC服务器的方法,以便发现其他RPC服务器漏洞。

前言

在本博客系列的第一部分中,我们讨论了我们在FortiGuard实验室中使用的方法,以使用RPCView查找RPC服务器上的逻辑漏洞。因此,我们发现了Microsoft Universal Telemetry服务中的潜在漏洞。

如果你仔细阅读了上篇文章,就会知道我们的分析步骤如下:

1.首先将所有RPC接口从RpcView GUI导出到文本文件,生成的文本文件包含可从RPC服务器调用的所有RPC API。

2.我们从输出文本文件中查找接受宽字符串作为输入的RPC API,直到发现来自diagtrack.dll的一个更有趣的RPC接口。

但是,我们本文的目的不是将所有RPC信息反编译并导出到文本文件中。幸运的是,在阅读源代码时,我们发现其中已经包含了我们需要的功能,但是默认情况下它不会被启用,只能在调试模式下使用特定的命令行参数被触发。由于此限制,RPCView(识别运行在Windows操作系统上的RPC服务的一个非常方便的工具)不会显示默认情况下在Windows上没有自动启动的RPC服务——例如数据共享服务。我们会在本文中,采用一些办法来识别此服务。事实证明,RPC服务还会遇到一些权限升级漏洞,这些漏洞我们都会在下面一一解答。

去年12月,Google安全研究员James Forshaw使用RPCView报告了由MSRC(Microsoft Security Response Center)修复的四个漏洞。因此,虽然使用RPCView仍然有用,但它也很耗时,因为你必须逐字审核所有接受字符串的API。所以我们想找到其他节省时间的方法。

首先,我们分析了一组以前发现的非常相似的漏洞。确定它们之间有一个共同点,因为它们都调用SetNamedSecurityInfo Windows API,该API允许程序通过对象名称在指定对象的安全描述符中设置指定的安全信息。例如,如果文件名是file对象,程序可以指定文件名。

我们想强调的是,虽然这个Windows API不构成任何安全漏洞。但是,当我们使用我们编写的静态分析工具来搜索我们想要查看的RPC服务时,它可以作为过滤器。有了这些知识,我们可以创建了一个简单的工具,静态解析所有RPC服务可执行文件,试图寻找感兴趣的Windows API,以缩小我们需要进一步挖掘的RPC服务的范围。

不出所料,我们果然发现了一些有趣的RPC服务。臭名昭着的存储服务,也称为StorSvc,具有以前未被其他研究人员发现的多个权限提升漏洞。另外还有AppX部署服务器器,它容易受到最终可能导致权限提升的竞争条件的影响。最终,我们将这些漏洞报告给微软安全响应中心(MSRC),现在它们已经分别被修复,并编号为CVE-2019-0569CVE-2019-0766

现在,我们将讨论我们是如何发现这些漏洞的。

[+] Target: appidsvc.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary DACL modification: appidsvc.dll

[+] Target: AppVEntSubsystemController.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: AppVEntSubsystemController.dll

[+] Target: AppXDeploymentServer.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: AppXDeploymentServer.dll

       [*] Potential DLL with arbitrary deletion: AppXDeploymentServer.dll

       [*] Potential executable with arbitrary file modification with move: AppXDeploymentServer.dll

       [*] Potential DLL with arbitrary DACL modification: AppXDeploymentServer.dll

[+] Target: bdesvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: bdesvc.dll

[+] Target: bisrv.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary DACL modification: bisrv.dll

[+] Target: combase.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: combase.dll

       [*] Potential executable arbitrary deletion: combase.dll

[+] Target: cryptcatsvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: cryptcatsvc.dll

       [*] Potential executable with arbitrary file modification with move: cryptcatsvc.dll

[+] Target: cryptsvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: cryptsvc.dll

[+] Target: dhcpcore.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: dhcpcore.dll

[+] Target: dhcpcore6.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: dhcpcore6.dll

[+] Target: DiagSvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: DiagSvc.dll

[+] Target: diagtrack.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: diagtrack.dll

       [*] Potential executable arbitrary deletion: diagtrack.dll

       [*] Potential executable with arbitrary file modification with move: diagtrack.dll

       [*] Potential DLL with arbitrary DACL modification: diagtrack.dll

[+] Target: DmApiSetExtImplDesktop.dll

       [*] Is RPC server file

[+] Target: dot3svc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: dot3svc.dll

[+] Target: dpapisrv.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: dpapisrv.dll

[+] Target: dssvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: dssvc.dll

       [*] Potential DLL with arbitrary deletion: dssvc.dll

       [*] Potential executable with arbitrary file modification with move: dssvc.dll

       [*] Potential DLL with arbitrary DACL modification: dssvc.dll

[+] Target: dusmsvc.dll

       [*] Is RPC server file

[+] Target: edgehtml.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: edgehtml.dll

       [*] Potential DLL with arbitrary deletion: edgehtml.dll

       [*] Potential executable with arbitrary file modification with move: edgehtml.dll

       [*] Potential DLL with arbitrary DACL modification: edgehtml.dll

[+] Target: eeprov.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: eeprov.dll

[+] Target: efslsaext.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: efslsaext.dll

       [*] Potential executable arbitrary deletion: efslsaext.dll

[+] Target: FXSAPI.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: FXSAPI.dll

[+] Target: FXSSVC.exe

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: FXSSVC.exe

       [*] Potential DLL with arbitrary deletion: FXSSVC.exe

       [*] Potential executable with arbitrary file modification with move: FXSSVC.exe

[+] Target: iphlpsvc.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary DACL modification: iphlpsvc.dll

[+] Target: LogonController.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: LogonController.dll

[+] Target: lsasrv.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: lsasrv.dll

       [*] Potential executable with arbitrary file modification with move: lsasrv.dll

[+] Target: mispace.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: mispace.dll

       [*] Potential executable arbitrary deletion: mispace.dll

[+] Target: modernexecserver.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary DACL modification: modernexecserver.dll

[+] Target: msdtcprx.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: msdtcprx.dll

       [*] Potential executable with arbitrary file modification with move: msdtcprx.dll

       [*] Potential DLL with arbitrary DACL modification: msdtcprx.dll

       [*] Potential executable with arbitrary file modification with move: msdtcprx.dll

[+] Target: netlogon.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: netlogon.dll

       [*] Potential executable with arbitrary file modification with move: netlogon.dll

[+] Target: p2psvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: p2psvc.dll

[+] Target: PackageStateRoaming.dll

       [*] Is RPC server file

[+] Target: pcasvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: pcasvc.dll

       [*] Potential executable with arbitrary file modification with move: pcasvc.dll

[+] Target: PeerDistSvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: PeerDistSvc.dll

       [*] Potential DLL with arbitrary deletion: PeerDistSvc.dll

       [*] Potential executable with arbitrary file modification with move: PeerDistSvc.dll

[+] Target: PhoneProviders.dll

       [*] Is RPC server file

[+] Target: pla.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary DACL modification: pla.dll

       [*] Potential executable arbitrary deletion: pla.dll

       [*] Potential DLL with arbitrary deletion: pla.dll

[+] Target: pnrpsvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: pnrpsvc.dll

[+] Target: profsvc.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: profsvc.dll

       [*] Potential executable arbitrary deletion: profsvc.dll

       [*] Potential DLL with arbitrary DACL modification: profsvc.dll

[+] Target: rasmans.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: rasmans.dll

       [*] Potential executable with arbitrary file modification with move: rasmans.dll

       [*] Potential DLL with arbitrary DACL modification: rasmans.dll

[+] Target: rdpclip.exe

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: rdpclip.exe

[+] Target: scesrv.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: scesrv.dll

       [*] Potential DLL with arbitrary DACL modification: scesrv.dll

[+] Target: schedsvc.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: schedsvc.dll

       [*] Potential executable arbitrary deletion: schedsvc.dll

       [*] Potential DLL with arbitrary DACL modification: schedsvc.dll

[+] Target: SessEnv.dll

       [*] Is RPC server file

       [*] Potential executable with arbitrary file modification with move: SessEnv.dll

       [*] Potential executable arbitrary deletion: SessEnv.dll

       [*] Potential DLL with arbitrary deletion: SessEnv.dll

[+] Target: Spectrum.exe

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: Spectrum.exe

[+] Target: spoolsv.exe

       [*] Is RPC server file

       [*] Potential executable with arbitrary file modification with move: spoolsv.exe

       [*] Potential executable arbitrary deletion: spoolsv.exe

[+] Target: sstpsvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: sstpsvc.dll

[+] Target: StorSvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: StorSvc.dll

       [*] Potential DLL with arbitrary deletion: StorSvc.dll

       [*] Potential DLL with arbitrary DACL modification: StorSvc.dll

[+] Target: sysmain.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: sysmain.dll

       [*] Potential executable with arbitrary file modification with move: sysmain.dll

       [*] Potential DLL with arbitrary DACL modification: sysmain.dll

[+] Target: SystemEventsBrokerServer.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: SystemEventsBrokerServer.dll

       [*] Potential executable with arbitrary file modification with move:

[+] Target: tapisrv.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: tapisrv.dll

[+] Target: taskcomp.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: taskcomp.dll

       [*] Potential DLL with arbitrary DACL modification: taskcomp.dll

[+] Target: tellib.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: tellib.dll

       [*] Potential executable arbitrary deletion: tellib.dll

       [*] Potential executable with arbitrary file modification with move: tellib.dll

       [*] Potential DLL with arbitrary DACL modification: tellib.dll

[+] Target: termsrv.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary DACL modification: termsrv.dll

[+] Target: trkwks.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: trkwks.dll

       [*] Potential executable with arbitrary file modification with move: trkwks.dll

[+] Target: tttracer.exe

       [*] Is RPC server file

       [*] Potential executable with arbitrary file modification with move: tttracer.exe

       [*] Potential DLL with arbitrary DACL modification: tttracer.exe

[+] Target: uireng.dll

       [*] Is RPC server file

       [*] Potential executable with arbitrary file modification with move: uireng.dll

       [*] Potential DLL with arbitrary deletion: uireng.dll

       [*] Potential executable arbitrary deletion: uireng.dll

[+] Target: usermgr.dll

       [*] Is RPC server file

       [*] Potential executable with arbitrary file modification with move: usermgr.dll

       [*] Potential DLL with arbitrary DACL modification: usermgr.dll

[+] Target: vaultsvc.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: vaultsvc.dll

       [*] Potential executable arbitrary deletion: vaultsvc.dll

       [*] Potential executable with arbitrary file modification with move: vaultsvc.dll

[+] Target: vmrdvcore.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: vmrdvcore.dll

       [*] Potential executable arbitrary deletion: vmrdvcore.dll

       [*] Potential executable with arbitrary file modification with move: vmrdvcore.dll

[+] Target: w32time.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary DACL modification: w32time.dll

[+] Target: wevtsvc.dll

       [*] Is RPC server file

       [*] Potential executable with arbitrary file modification with move: wevtsvc.dll

       [*] Potential executable arbitrary deletion: wevtsvc.dll

       [*] Potential DLL with arbitrary DACL modification: wevtsvc.dll

[+] Target: wiaservc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: wiaservc.dll

[+] Target: wifinetworkmanager.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: wifinetworkmanager.dll

       [*] Potential DLL with arbitrary deletion: wifinetworkmanager.dll

[+] Target: wimserv.exe

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: wimserv.exe

       [*] Potential DLL with arbitrary deletion: wimserv.exe

[+] Target: Windows.Internal.Bluetooth.dll

       [*] Is RPC server file

[+] Target: wininit.exe

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: wininit.exe

       [*] Potential executable with arbitrary file modification with move: wininit.exe

[+] Target: winlogon.exe

       [*] Is RPC server file

       [*] Potential executable with arbitrary file modification with move: winlogon.exe

[+] Target: wlansvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: wlansvc.dll

       [*] Potential executable with arbitrary file modification with move: wlansvc.dll

[+] Target: wwansvc.dll

       [*] Is RPC server file

       [*] Potential executable arbitrary deletion: wwansvc.dll

       [*] Potential executable with arbitrary file modification with move: wwansvc.dll

[+] Target: XblGameSave.dll

       [*] Is RPC server file

       [*] Potential DLL with arbitrary deletion: XblGameSave.dll

       [*] Potential executable arbitrary deletion: XblGameSave.dll

       [*] Potential executable with arbitrary file modification with move: XblGameSave.dll

由静态解析器过滤的RPC可执行文件

CVE-2019-0569——任意文件覆盖Microsoft Windows存储服务  

如上图所示,在分析由静态解析器过滤的RPC可执行文件时,它指出了包含我们所需的导入API的StorSvc.dll。在反汇编DLL组件时,我们发现了这个接口:BE7F785E-0E3A-4AB7-91DE-7E46E443BE29,当反汇编其中一个公开的RPC API时,我们发现了一个名为SvcSetStorageSettings的有趣RPC API。这引起了我们的注意,因为这个API涉及创建两个具有可预测文件夹名称的Windows目录。将正确的参数传递给这个API时,将在外部存储驱动器卷的根目录上创建以下文件夹:

· 文件

· 影片

· 图片

· 下载

· 音乐

你可能已经注意到,这些是在用户帐户配置文件根目录下找到的相同默认文件夹(%USERPROFILE%)。但是,漏洞是,如果存在外部硬盘驱动器卷,这些文件夹将仅由RPC API创建。当RPC API被触发时,你可以看到Process Monitor(一款系统进程监视软件)输出类似于下面屏幕截图中显示的输出:

2.png

SvcSetStorageSettings创建的多个硬编码文件夹

查看Process Monitor输出的内容,我们可以看到此RPC API容易受到符号链接攻击(一次完美的符号链接攻击,除了必须有符号链接外,更重要的是要有提权的渠道。)因为它会创建一些可预测的目录。从Process Monitor调用堆栈信息中,我们可以确定特定CreateFile事件中涉及的函数例程。在查看相关函数例程时,我们很快在StorageService::CreateStorageCardDirectory中发现了漏洞,在创建经过身份验证的用户可以访问的文件和文件夹时,这个目录缺少模拟过程,以至于它允许攻击者修改通过符号链接指定的任意文件对象的ACL。

我们来看下面的代码片段:

StorageService::CreateStorageCardDirectory()
{
       dwFileAttributes = GetFileAttributesW(&FileName);
       if ( dwFileAttributes != -1 && !(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) // -- (1)
       {
               DeleteFileW(&FileName);                            
               dwFileAttributes = -1;
       }
                     
       if (CreateDirectoryW(&FileName, lpSecurityAttributes) )     // -- (2)
       {
               if (dwFileAttributes != -1 && (ExistingFileAttributes | 0x10) != (dwFileAttributes & 0xFFFFFFDF) )
                      SetFileAttributesW(&FileName, ExistingFileAttributes | 0x10)
       }
       else if (GetLastError() == ERROR_ALREADY_EXISTS)
       {
result = SetNamedSecurityInfoW(&FileName, SE_FILE_OBJECT, SECURITY_DACL_INFORMATION, 0, 0, NewAcl, 0);                                                        // -- (3)
               boolSetNameddSecInfo = result < 0;
               if ( result > 0 )
               {
                      result = (unsigned __int16)result | 0x80070000;
                      boolSetNameddSecInfo = result < 0;
               }
               if (!boolSetNameddSecInfo)
               {
                      dwFileAttributes = GetFileAttributesW(&FileName);
                      SetFileAttributesW(&FileName, ExistingFileAttributes | 0x10)
               }
       }
}

有漏洞的StorageService::CreateStorageCardDirectory缺少模拟过程

如果攻击者成功地创建了一个符号链接,将文件名重定向到攻击者想要的文件对象,则可以使用NewAcl(即当前登录用户的ACL)在label(3)中的代码路径上修改重定向文件对象的ACL。

符号链接攻击发生之前,我们需要处理标签(1)和(2)中的条件检查。简而言之,我们确定(1)和(2)中的条件检查将删除文件并尝试在发生文件名冲突时创建具有相同名称的目录。需要注意的是,在创建目录之前,它会执行DeleteFileW,删除指向目标文件的符号链接。那么,我们如何防止符号链接被删除呢?

事实证明,如果文件名具有调用者进程打开的独占文件句柄,则可以很容易地绕过它。即使DeleteFileW调用失败并且漏洞访问被拒绝,执行进程仍将继续,因为从API调用返回时没有漏洞检查。

在我们设置指向目标文件的符号链接并在目标文件上创建了独占句柄之后,我们可以触发SvcSetStorageSettings来修改任意文件对象的ACL。以下屏幕截图中的PoC结果说明了SvcSetStorageSettings中的漏洞如何允许我们修改位于Windows目录中的文件的ACL。实际上,该ACL应禁止非权限用户修改:

4.png

使用svcsetstoragesetings RPC API的结果

CVE-2019-0766——Microsoft AppX 部署服务器通过竞争条件创建任意文件 

继续进行解析器的输出内容,我们发现另一个Windows AppX部署服务器也是由于缺乏模拟过程,出现了同样的符号链接攻击漏洞。

在安装可从Microsoft Store下载的AppX软件包时,我们意识到AppX部署服务器将AppX软件包可执行文件及其相应资源保存在以下可预测文件路径中:

E:\WpSystem\<current_logged_in_user_sid>\AppData\Local\Packages\Microsoft.AppX.Package.Name

如果部署服务器要修改同时删除的文件上的ACL,则可能会发生相同的符号链接攻击。注意:E: drive 是我们测试系统上的外部驱动器。你可能已经注意到,这与上一节描述的漏洞有点类似。但是,我们首先需要确定这个文件路径的可访问性。

我们可以使用icacls命令确定文件和文件夹的可访问性,事实证明,当前登录的用户具有对此目录的完全访问权限。

C:\>icacls E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData\Local\Packages\Microsoft.MicrosoftMahjong_8wekyb3d8bbwe
E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData\Local\Packages\Microsoft.MicrosoftMahjong_8wekyb3d8bbwe
NT AUTHORITY\SYSTEM:(CR)(F)
NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(CR)(F)
DESKTOP-A7ABC1O\researcher:(CR)(F)
DESKTOP-A7ABC1O\researcher:(OI)(CI)(IO)(CR)(F)
BUILTIN\Administrators:(CR)(F)
BUILTIN\Administrators:(OI)(CI)(IO)(CR)(F)
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
DESKTOP-A7ABC1O\researcher:(I)(OI)(CI)(F)
 
C:\>icacls E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData\Local\Packages
E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData\Local\Packages
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
DESKTOP-A7ABC1O\researcher:(I)(OI)(CI)(F)
                                                                                                                                                                 
 
C:\>icacls E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData\Local
E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData\Local        
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
DESKTOP-A7ABC1O\researcher:(I)(OI)(CI)(F)
                                                                                                                                               
C:\>icacls E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData            
E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001\AppData     
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
DESKTOP-A7ABC1O\researcher:(I)(OI)(CI)(F)
                                                                                                                                               
C:\>icacls E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001                                      
E:\WpSystem\S-1-5-21-2264505789-2271452246-4192020221-1001    
NT AUTHORITY\SYSTEM:(OI)(CI)(F)
BUILTIN\Administrators:(OI)(CI)(F)
DESKTOP-A7ABC1O\researcher:(OI)(CI)(F)

显然,普通用户帐户可以任意操纵具有较高权限服务共享的资源。有两种方法可以验证此漏洞:如前一篇文章中所述,你可以使用Process Monitor在AppX软件包安装期间捕获事件,并从那里通过查找SetSecurityFile事件来查明代码路径。而另一种方法就是对DLL组件AppXDeploymentServer.dll执行静态分析,该组件包含服务逻辑的实现。

我们最终得到了以下代码片段:

// After created its parent directories, try to create E:\WpSystem\<SID>\AppData\Local\Packages\<AppX.PackageName>
        if ( CreateDirectoryW(*(LPCWSTR *)(this - 28), 0) )           // -- (1)
          v16 = 0;
        else
          v16 = getlasterror();
        v15 = *(void **)(this + 4);
        if ( v16 < 0 )
        {
          v17 = 0x4C8;
          goto exit;
        }
      }
      v15 = *(void **)(this + 4);
      if ( v16 >= 0 )
      {
        if ( v13 == 1
          || sub_102335C9(v15)
            // Set security descriptor on e:\WPSystem and its sub-directories to allow Administrator and System user access only
          || (v19 = wpsystem_setnamedsecurityinfo((int)v12, *(WCHAR **)(this - 16)),
              v15 = *(void **)(this + 4),
              v16 = v19,
              v19 >= 0) )
        {
          // Encrypt and compress the files in Appx.Package
          v20 = EncryptFile((int)v12, *(WCHAR **)(this - 16));     // -- (2)
          v15 = *(void **)(this + 4);
          v16 = v20;
          if ( v20 >= 0 )
          {
            // Reset security descriptor on \\?\E:\WpSystem\<SID>\AppData\Local\Packages\<AppX.PackageName> to allow full access
           // however, neither no verification is done on the assigned object name therefore it can be replaced with file object instead of directory object and impersonation here
            v21 = SetNamedSecurityInfoW(*(LPWSTR *)(this - 28), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, *(PACL *)(this - 20), 0);            // -- (3)

AppXDeploymentServer.dll缺少用户模拟

正如你在上面的代码片段中所看到的,在(1)中标记的AppX包目录与通过(3)中标记的SetNamedSecurityInfoW设置其安全描述符之间存在潜在的竞争条件,这可能允许攻击者修改任意文件对象的ACL。

为了验证这一点,我们的目标是通过符号链接将AppX文件夹名称,SetNamedSecurityInfoW的第一个参数(由label(3)中的代码指示)重定向到感兴趣的任意文件对象。

但是,在此之前,请务必注意默认保存位置需要设置为外部驱动器。在Windows 10中,这可以在“控制面板”中的“默认保存位置”设置下完成,但我们希望以编程方式执行此操作。如前一个案例研究中所述,找到了SvcSetStorageSettings RPC API后,它可以用来直接更改默认的保存位置。但是在程序中定义RPC接口是一个非常繁琐的步骤,所以我们需要一种更方便的方法来实现这一点。

事实证明,大多数RPC API都是通过单个DLL组件进行封装和导出的。因为大多数封装的RPC API导出函数都是未记录的,并由Windows系统组件实现,我们需要做的是通过在%WINDIR \ SYSTEM32目录中搜索其RPC UUID来查找此DLL。在我们使用其UUID(即BE7F785E-0E3A-4AB7-91DE-7E46E443BE29)搜索SvcSetStorageSettings接口后,会发现StorageUsage.dll,我们在其中发现了SetStorageSettings未记录的API。因此,我们可以使用常规LoadLibrary()和GetProcAddress()动态调用这个API。

最后,我们准备了PoC,并使用Process Monitor运行它来说明竞争条件,如下面的屏幕截图所示:

7.png

演示无限循环线程的PoC屏幕截图

1.表示我们的PoC正在执行无限循环线程操作,试图删除列表3中label(1)中的代码创建的AppX文件夹;

2.表示AppX部署服务器成功创建的AppX文件夹;

3.线程会立即成功删除该文件夹;

8.png

修改ACL操作的PoC屏幕截图

4.此时,AppX 部署服务器尝试通过执行wpsystem_setnamedsecurityinfo例程来修改目录及其子目录的安全描述符。然而,由于(a)处的操作导致文件即将被删除,所以操作没有成功。

5. 列表3中的代码标签(2)中提到的操作将在此时执行;

9.png

PoC屏幕截图,用于说明竞争条件的成功利用

6.竞争条件成功利用后,我们的PoC将能够在执行列表3中的代码标签(3)之前,在PoC中创建任意文件C:\Windows\system32\ license.rtf的符号链接;

7.最后,权限服务成功修改了目标文件的安全描述符

10.png

成功利用竞争条件覆盖任意文件对象的PoC

总结

本文,我们介绍了在寻找本地权限提升漏洞时,如何缩小搜寻的RPC服务范围。目前,这种方法已被证明非常有效,如上所述,我们发现了CVE-2019-0569 和 CVE-2019-0766漏洞,但是在不同的组件中。

研究人员发现,恶意软件可以向CT扫描结果中注入假的癌症特征或删除已存在的癌症特征。

当前,信息系统已成为医院各部门业务开展的必备工具,是实现医院现代化运营的重要手段。但若信息安全出现问题,小则影响医院业务开展甚至停摆,大则影响社会安定。

医院信息安全主要包括设备安全、网络安全、数据安全及行为安全。如中心机房服务器、存储器、交换机等设备安全,医院内部网络及互联网接入安全,各科室终端安全(如开机密码保护、文档资料、USB接入等安全)信息系统中患者病历数据、个人隐私安全等,甚至包括个人的科研成果、项目文档、银行及支付账户安全等。

最近,来自以色列本•古里安大学网络安全研究中心的两位研究人员正在展示的一种恶意软件不仅可以改变CT扫描结果,还可以通过这种方法来设法欺骗专业人员对于癌症存在的判断,并可能导致误诊。

由于解读CT扫描和MRI图像是件非常专业且复杂的事情,所以现在对它们的分析在某种程度上都是依赖专业的放射科医生和肺癌筛查软件完成的。一旦利用了软件,则黑客就有了可乘之机。

一项涉及70项改良CT肺部扫描的盲法研究证明,放射科医生和肺癌筛查软件一直把CT扫描结果中存在节点确认为癌细胞,但事实是:这些节点和癌细胞没有半点关系。

1e401def35dd438.jpg

恶意软件能够以惊人的准确度改变这些图像的结果(注入假的癌症特征或删除已存在的癌症特征),虽然这些软件可能会进行一些检查和备份以确保诊断正确,但单靠此类软件仍是弊大于利。

这次的研究结果表明,误诊除了有恶意软件本身的问题外,还存在一个令人担忧的问题,即医院如何保护数据免受诸如此类恶意软件的攻击。

威胁信息安全的主要方式包括病毒、木马及人为的特定攻击等。攻击者通过篡改网页源代码、利用系统漏洞加入木马程序等,对用户进行攻击,盗取用户重要数据,迫使用户满足其提出的要求。

严格授权管理  

根据医院信息系统权限分配管理办法,用户提出需求,须严格控制其身份认证及授权,区分不同级别的用户,定期提醒其修改密码,且密码须为字母加数字组合,甚至可采用不易破解的动态密码技术,对用户实行身份和操作的合法性认证,如有条件的医院,可考虑使用CA。

有报告指出:医疗行业是唯一的内部人员对组织造成最大威胁的行业。58%的数据泄露事件涉及内部人员,而外部参与者造成的事件不到一半。

在暗网上,完整的医疗记录(如患者姓名,出生日期,社会安全号码和医疗信息)每份可以卖50美元,而社保号码只需15美元。被盗信用卡的售价仅为1美元至3美元。医疗记录可能被用于各种各样的恶意目的,从医疗保健欺、身份盗窃到开辟新的信贷额度,敲诈勒索和敲诈勒索等。

那么应该采取哪些保障措施来最大限度的降低接触外部或内部威胁因子的风险?医疗服务提供者可以采取3项基本措施来增强其安全态势:

员工安全意识培训:推动组织中的文化变革,将安全实践纳入日常运营,并确保实施这些变革所需的财务资源。

数据加密——未加密设备的被盗或错位继续导致医疗保健市场中的数据泄露。

使用多重身份验证(MFA)补充密码:由于MFA需要多种识别方法,因此它是防止未经授权的用户访问敏感数据并在网络中横向移动的最佳方法之一。

实施最低访问权限和特权:考虑到医疗保健行业中特权访问滥用的比例很高,通过采用零信任安全方法来限制访问和特权是至关重要的。这需要建立细致的、基于角色的访问控制,以限制横向移动,以及对应用程序和基础设施的即时特权。

定期自查检测  

定期对医院信息系统的安全状况进行自查,对网络系统进行全面安全检测。检测的内容包括:服务器、存储设备、网络设备及操作系统等是否存在安全漏洞,根据安全需要对系统进行安全修复和加固,比如升级、漏扫等。

数据安全备份  

医院数据中心存放着大量数据,正所谓"硬件有价,数据无价",为保证数据安全,可进行三种方式的数据备份:一是租用"云空间",将数据备份至"云端",甚至可将医院核心业务服务端转移至"云端",但须掌握"云"安全知识;二是建设异地容灾系统,即在外地租用空间,通过光纤或互联网专线传输,定时(或实时)进行数据备份;三是利用数据库技术每天定时自动备份数据库文件到指定位置。

提供对外合作  

明确一家安全服务机构,当医院遇到突发的安全事件时,安全服务机构能够提供应急响应服务,并立即配合医院信息中心人员进行处理。

参考:https://sec.today/pulses/fc8962f5-2c3e-42f7-b0b0-9be0a5cf1e65/

简化、优化你的补丁管理

许多攻击机制,都是针对未修补的系统。所以,不管你的网络是否对外开放,都应该定期更新操作系统和应用程序。虽然这个建议属于老生常谈,但从另一个侧面也说明了该建议的重要性。

对于Windows系统来说,利用Windows Server进行更新服务简单而高效。 利用WSUS部署更新程序时,WSUS易于设置,可以设置为自动或手动方式,而利用第三方软件来管理更新就有点不靠谱了。

审核默认密码

目前已确认的数据泄露事件均涉及到密码口令的丢失、密码口令安全性过低或默认密码未更改有关,所以这个建议是非常重要的。当用户在首次使用设备时,应该先对默认的出厂密码进行修改,如果没有设置密码的要先设置密码,但往往人们会忽略这些关键的保护手段。攻击者就是利用这些疏忽来进行攻击的,因为一般的出厂默认密码都可以在网络上查到。攻击者可以利用网络设备,如交换机和接入点上的默认密码来重定向流量,执行中间人攻击,或对网络基础设施执行拒绝服务攻击。更糟糕的是,内部系统所利用的Web控制台在包含敏感业务数据或系统配置的应用程序中通常使用的都是默认密码。攻击者利用网络钓鱼和常见的恶意软件的攻击向量就可以绕过安全防护。

加强内部防护,特别是供应链攻击

内部攻击有两种,一种是内部人员有意进行的恶意行为,另一种是供应链攻击的被动攻击行为。

最近两年,供应链攻击已经成为最大网络威胁 。供应链攻击形式多样。可以是对合作伙伴公司的雇员进行网络钓鱼获取本公司登录凭证,比如近几年影响最重大的两起数据泄露:美国零售商塔吉特百货和美国人事管理局(OPM)数据泄露事件,就是经由合作公司失窃的登录凭证。也可以是往合法软件中植入恶意软件,比如著名的NotPetya勒索软件,就是乌克兰流行会计软件M.E.Doc被感染而引起的。英国国家网络安全中心(NCSC) 对供应链攻击的总结如下:

如果做得好的话,供应链攻击是很难被检测出来的,有时候甚至是完全不可能被发现的。网络监视能检测出异常或可疑行为,但依然难以确定安全漏洞是有意引入的(可能是作为后门),还是来自开发人员或制造商的无意疏忽,或者其实是为了证明有潜在的访问凭证被利用了。

使用LAPS管理本地管理员密码

在2015年年中,微软发布了一个解决这个该问题的工具,即本地管理员密码解决方案(LAPS)。此方案是将本地管理员密码存储在LDAP上,作为计算机账户的一个机密属性,配合GPO,实现自动定期修改密码、设置密码长度、强度等,更重要是该方案可以将该密码作为计算机帐户属性存储在Active Directory中。该属性“ms-Mcs-AdmPwd”可以通过ACL锁定,以确保只有经过批准的用户,如控制台和系统管理员可以查看密码。 LAPS还包括一个PowerShell模块和一个后台客户端,LAPS UI,以简化管理和检索过程。 

LAPS实现起来非常快速简单,只需要要求系统管理员创建一个定义密码策略和本地帐户名称的GPO来管理,可以直接将单个文件AdmPwd.dll添加到Windows上。

注意漏洞披露时保护关键细节

攻击者利用这些信息制定攻击策略,例如内部IP地址,敏感文件的本地路径,服务器名称和文件共享。从这些信息可以推断出其他的运行环境特征,并可以帮助攻击者更清楚地了解你的操作环境。一般情况下,很少有用户会查看错误信息的详细原因。

禁用LLMNR和NetBIOS名称解析

链路本地组播名称解析(LLMNR)和NetBIOS名称服务(NBT-NS)都可以导致在启用时快速对域名进行攻击。这些协议最常用在初始DNS查找失败时查找所请求的主机,并且会在默认情况下启用。在大多数网络中,由于DNS的存在,所以LLMNR和NetBIOS名称解析根本就没有必要再用了。当对无法找到的主机发出请求时,例如尝试访问\\ dc-01的用户打算输入\\ dc01,LLMNR和NBT-NS就会发送广播,寻找该主机。这时攻击者就会通过侦听LLMNR和NetBIOS广播,伪装成用户(客户端)要访问的目标设备,从而让用户乖乖交出相应的登陆凭证。在接受连接后,攻击者可以使用Responder.py或Metasploit等工具将请求转发到执行身份验证过程的流氓服务(如SMB TCP:137)。 在身份验证过程中,用户会向流氓服务器发送用于身份认证的NTLMv2哈希值,这个哈希值将被保存到磁盘中,之后就可以使用像Hashcat或John Ripper(TJR)这样的工具在线下破解,或直接用于 pass-the-hash攻击。

由于这些服务通常不是必需的,因此最简单的措施是完全禁用它们。大家可以按着计算机配置 – >策略 – >管理模板 – >网络 – > DNS客户端 – >关闭组播名称解析来修改组策略,禁用LLMNR。

而禁用NetBIOS名称解析并不是一件简单的事情,因为我们必须在每个网络适配器中手动禁用“启用TCP / IP NetBIOS”选项。

查看当前账户是否具备管理员权限

攻击者对账户进行控制时,会尽一切办法来获得该设备的管理权限,比如用户有时会为了某种访问的需要,进行一些临时访问,但在访问完毕后,用户有时会忘了对这些访问进行删除或监控,以至于被黑客利用。根据实际监测,很少有用户会把这些临时访问权限进行删除。

具有域管理员或企业管理员资格的帐户应受到高度限制,比如只能用于登录域控制器,具有这些权限的帐户不应再在其他系统上进行登录了。在此,我们建议大家可以基于不同的管理功能来为每个账户设置不同的权限的管理账户,比如 “工作站管理”和“服务器管理”组,这样每个管理员就不具有访问整个域的权限了,这将有助于对整个域的权限保护。

及时查看你的网络设备是否被攻击

如果你登陆过https://www.shodan.io这个网站,你一定会被其中所曝光的敏感漏洞和服务而震惊。与谷歌不同的是,Shodan不是在网上搜索网址,而是直接进入互联网的背后通道。Shodan可以说是一款“黑暗”谷歌,不停的在寻找着所有和互联网关联的服务器、摄像头、打印机、路由器等等。每个月Shodan都会在大约5亿个服务器上日夜不停地搜集信息。

如果没有必要就不要将你的设备接入网络

如果没有必要就不要把你的设备连接到互联网,不过要知道网络上有哪些型号的设备已经被攻击了,建议大家尝试使用端口扫描之王——nmap进行扫描,端口扫描是指某些别有用心的人发送一组端口扫描消息,试图以此侵入某台计算机,并了解其提供的计算机网络服务类型(这些网络服务均与端口号相关),但是端口扫描不但可以为黑客所利用,同时端口扫描还是网络安全工作者的必备的利器,通过对端口的扫描,了解网站中出现的漏洞以及端口的开放情况。比如,像“nmap -sV -Pn -top-ports 10000 

1.2.3.4/24”这样的简单扫描可以让我们快速了解攻击者可能看到的内容,利用Shodan和Censys.io这样的工具就可以做到自动搜索这些内容。

尽量使用专有的设备管理网络

扁平网络虽然易于管理和使用,但是对于攻击者来说也一样非常方便进行攻击。所以为了加强对设备的管理和安全预防,目前,主流厂商售出的大部分服务器都使用专用硬件模块或特殊的远程管理卡提供管理接口,通过专用的数据通道对设备进行远程维护和管理,完全独立于设备操作系统之外,甚至可以在设备关机状态下进行远程监控与管理。

进行渗透测试

虽然进行渗透测试的成本会很大,但是对于大型组织机构来说,我还是觉得有必要这样做。比如一家企业在执行网络安全检测时,可能会倾向于或固定使用某一种方法,时间一长就会形成一种定性思维,对某些潜在问题或某一类问题忽略。雇用安全专家来模拟一个攻击者的行为来对你的组织进行一次攻击,会让你产生不同的防御思路,并及时和最新的安全趋势进行对接。在此大家可以参考一下《一次神秘的测试——通过打印机找到父域控制器》,看看测试者是如何通过一台打印机开始对整个组织的攻击的。在渗透测试中,永远不要忽视你在评估中发现的哪怕是最细微的信息,在你不知道这些信息有多大的作用时,请保持对它们的关注。

(接上文)

29.png

看一下该函数,arg_0(XOR密钥)用于Rotate Left指令。下图中,可以看到BL被移动到CL中,它增加1并用于将XOR密钥向左旋转1,这会产生用于解密BSS字符串的最终XOR密钥。

30.png

一旦执行了这些计算,就会得出这个密钥:0x249d730c。虽然可以从调试程序获取字符串并将其复制到IDA示例,但我更喜欢使用Python复制自定义例程。简单地说,该算法混合使用了XOR和rotate right (ROR)指令来解密DWORD中的数据。首先,我要复制BSS部分中的数据。在十六进制编辑程序模式下查看它,选择整个部分(有数据的地方),然后点击编辑 – >导出数据。接下来,我需要解析这些数据,进而进行解密。

31.1.png

31.2.png

要解析它,我将使用python。我们所需要做的就是将十六进制字节除以4,并将结果存储在一个列表中。这意味着每个值都是一个DWORD。按照以下命令,你应该能够得到如图所示的输出。

32.png

接下来,我将使用CyberChef(一款开源网络工具)进行更多分析,由于我替换了字符,因此在每个DWORD之前都有一个0x,因此Python不会将列表视为字符串列表。

33.png

如果一切顺利,此时现在你应该有一个合适的十六进制DWORD列表。为了解密该列表,你只需将其复制到脚本中并确保密钥正确,然后它将被解密并输出原始数据以及整数列表。在下图中,你可以看到脚本的解密过程,不是太复杂。

34.png

一旦解密完成,就会有如下所示的输出。

35.png

现在我可以将解密的字符串复制到IDA,下图中有一个IDA Python脚本,它用数据中的数据字节覆盖dest中的字节。列表数据将包含我的脚本打印到终端的整数值,因此你只需从中复制它并将其粘贴到文档中即可。

36.png

此时,我需要将其作为IDA中的脚本或模块导入,为此你可以通过导入文件或复制文本并将其粘贴到框中来执行此操作。

37.png

在将PatchArr()输入控制台并按下回车键后,脚本应该用解密的字符串覆盖BSS部分的所有字节,此时,你应该看到类似于下图中的内容。

38.png

然后,我可以通过选项->通用->分析->重新分析程序重新分析有效载荷,它应该识别大多数字符串,尽管偶尔会出现错误。

39.png

使用新解密的BSS部分,我们应该能够分析出其余的有效载荷。

一旦字符串被解密,ISFB就会调用一个函数,该函数使用其中一个解密的字符串——IsWow64Process,它将检查系统是否为64位,然后测试结果(如果是x64,则存储在EAX – 1中,如果不是x64,则存储在0中)。如果系统不是64位的,那么下图中的变量var_4将用于EAX的AND操作,此时,它将等于0,这意味着var_4中的值将为0。如果系统是64位的,则自动跳过。不管系统体系结构如何,var_4中的值都会被移动到EAX中,即返回值。

40.png

如果退出函数,我可以看到EAX再次被测试,如果结果不为零,则值1将移动到DWORD dword_405478。由于我运行的系统是64位,dword_405478将包含值1。如果我搜索对此DWORD的交叉引用,可以找到使用它的测试指令,因此我可以确定这是系统架构的一个指示器。

41.png

调用的下一个函数非常复杂,简而言之,此函数负责将地址发送给少数几个API调用。为此,它使用一个预定义值列表,一个“密钥”和一个哈希例程。首先,找出密钥。查看下图,就在hModule中的值移入ECX之前,EAX与二进制文件中的DWORD进行了异或运输,但是在查看此DWORD时,它是空的,这意味着它是动态解析的。

42.png

要找出这个DWORD将包含的内容,我需要找到对它的交叉引用,具体来说,就是寻找一个引用它作为MOV指令中的目标。幸运的是,我在BSS解密函数中发现了它。从下图中,我可以看到来自字符串的DWORD被移动到ECX中,然后在减法和加法指令中进行使用。现在,就可使用反编译器中查看具体的过程。

43.1.png

43.2.png

如下图所示,从它的外观来看,我可以通过执行简单操作来获取所使用的密钥。

43.jpg

我可以通过查看调试程序中的二进制文件来仔细检查这一点,如下图所示。

44.png

在找到密钥后,就来看看哪个API的值要被导入。这很容易找到,因为它已经存在于可执行文件中了。另外,我还可以看到EDI被用作计数器,因为每个循环都将其递增4,直到值达到20,这意味着总共有5个API使用此方法来查找。嵌入列表中的值全部由密钥进行异或,这会产生用于比较的哈希查找值。我可以从中找到对应的哈希算法,并确定查找和存储哪些API。

45.png

45.2.png

由于函数非常大,我将重点介绍调用哈希函数的部分。传递给这个函数的三个参数是; DLL的地址,值0和用于比较的正确哈希。该函数使用基址执行一些计算,以便得到DLL内的导出表。此时,它会遍历每个导出并哈希导出的名称,然后将其与预定义的哈希进行比较。如果哈希值匹配,则该函数将检索导出的API的地址,并使用该地址覆盖预定义的哈希以供以后使用。如果它们不匹配,则该函数将继续进行下一次导出,直到最终发现匹配的哈希值为止。

46.png

46.2.png

查看实际的哈希函数,在调试器中运行该函数之前,很难得出该函数负责哈希的结论,对于初学者尤其如此。从静态分析的角度来看,这个函数中肯定发生了一些事情,因为有多个逻辑指令,但是在进一步分析之前,我们也不能确定这个猜测。

47.png

查看调试器,很明显,[edx*4+404108]和[ecx*4+404108]是查找表中的值,因为使用的XOR值不断变化,但是这些值是重复的,因此我可以确定它们不是随机的。当我查看查找表所在的存储区域时,很容易看到它的开始和结束位置。那么,知道有一个查找表后,我如何找出正在使用的哈希机制呢?

48.png

通常,自定义加密和哈希实现很难确定,除非你知道自己在寻找什么。只要该算法是公开可用的(例如AES或Serpent),而不是开发者自定义开发的算法,那么几乎总会有特定的值或指令作为常数出现。本文的示例中,常数就是0xA00AE278。如下图所示,这个值肯定与CRC-32有关。

49.png

在这个特定的示例中,程序循环遍历NTDLL.DLL导出函数并将它们全部哈希,直到找到匹配的哈希。更糟糕的是,哈希是不可逆转的,这意味着你可以找到匹配哈希的唯一方法是通过强制执行。这样做,你就可以哈希NTDLL导出的每个API,直到你找到匹配的哈希值,但这太费时了。简单的办法就是,在找到匹配项的命令上放置一个断点,然后执行程序。一旦断点被触发,你将能够找到正确的API。从下图中,你可以看到匹配的第一个API调用是ZwGetContextThread,我现在可以使用它来获得使用的CRC-32的变体。

50.png

在此,我推荐使用https://crccalc.com/转换网站,它允许我将调试程序的值与不同变量的输出进行比较。使用API名称ZwGetContextThread和所需的输出0x5A3D66E4,我可以找到使用的变体:CRC-32 / JAMCRC。

51.png

匹配的API被找到后,就不需要编写强制执行脚本了。但对于像GootKit这样的恶意家族来说,强制执行脚本还是有必要编写的。因此,导入的5个API是:ZwGetContextThread,ZwSetContextThread,ZwReadVirtualMemory,ZwWriteVirtualMemory和ZwAllocateVirtualMemory。

52.1.png

52.2.png

下一个函数只是检索要存储在存储区域中的文件名,它可能会在稍后的示例中使用。现在我想跳过它,分析它后面的更有趣的函数。

53.png

由于ISFB被嵌入FJ,F1或JJ结构,此结构位于节表之后,包含指向附加数据的指针,例如配置信息,RSA公钥,甚至是另一个可执行文件。 虽然FJ,F1和JJ之间存在差异,但它们的变化很小。本文的样本使用的是嵌入式JJ结构,可从魔术值0x4A4A(“JJ”)中被识别出来。

54.png

该结构的格式如下所示:

55.jpg

该二进制文件的解析结构如下:

56.jpg

我正在查看的函数负责解析此结构并查找所需的数据,这个函数的主要参数是第三个,它是“pnls”字符串和嵌入的十六进制值之间的XOR的结果。第一个和第二个参数只是代表一个空的存储区域的开始和结束,因此它们现在并不那么重要。

57.png

解析函数的前半部分时要遍历MZ和PE标头,直到进入位于节表之后的资源结构为止。魔术值实际上是“JJ”(0x4A4A),否则它将把0x14添加到当前地址并重试。

58.png

一旦结构确定了,该函数就会将第三个参数(0x9E154A0C)与嵌入的CRC-32哈希值进行比较,后者也是0x9E154A0C。如果不匹配,则该函数将再次返回或循环。如果它们匹配,则函数对结构标志和0x2执行bitwise AND,直到返回0,否则函数将一直循环或返回。如果返回0,则根据存储在结构中的大小值分配堆。一切都结束后,该函数将通过将结构中的地址添加到可执行文件的基址来获得联接数据的完整存储地址,然后对结构标志和0x1执行bitwise AND。如果结果为0,则联接数据( joined data)不会被压缩并被编码,如果结果不为0(在本文的示例中为1),则会压缩联接数据。由于在这个二进制文件中压缩了联接数据,我们将重点介绍压缩方法。

59.png

推送到函数的两个参数分别是压缩数据的位置,以及新分配的堆的地址。

60.png

你可以看到该函数非常复杂且很难理解,还记得我之前所说的常数值吗?它们也存在于一些压缩例程中,尽管与加密算法相比,识别算法要困难得多。

61.png

由于我会在上图中寻找一个没有存储在存储区域中的硬编码,所以我可以看到正在使用的一条CMP指令,将esi中的值与值0x7D00进行比较。使用此功能,我可以在Google上搜索“0x7d00压缩”。

62.jpg

63.png

根据明显的相似之处,我可以推断出这里使用的解压算法是APLib。根据这些信息,我就可以编写一个简单的提取脚本来从二进制文件中提取任何联接数据,并使用由Mak创建的优秀Python库Mlib对其进行解压。在十六进制编辑器中打开二进制文件,并找到联接数据的位置,识别字符串。

64.png

从解压缩函数中退出后,恶意程序将确保解压缩的可执行文件的大小与JJ结构中存储的值大小相同。如果大小不匹配,则使用HeapFree()从内存中清除已解压缩的可执行文件。然后,恶意软件用存储在结构中的XOR密钥对解压数据的第一个DWORD进行异或。看一下解压后的数据,我可以看到可执行文件的第一个DWORD无效,它应该看起来像00009000,而不是54205BD4。在XOR之后,可以看到有效值。该函数在自行清理后,然后返回调用函数。如果你在此阶段转储可执行文件并在开头添加“MZ”,则无法在PE Bear中打开它。

65.1.png

65.2.png

在调用函数中,恶意软件会使用滚动XOR算法覆盖已解压的可执行文件。我不确定它为什么这样做,可能是因为可执行文件稍后会被解密。无论如何,一旦可执行文件被加密,函数就会这样做。

66.png

首先,它创建一个新的文件映射,并调用MapViewOfFile,然后在调用UnmapViewOfFile之前将其文件名复制到新映射的区域。不过我不太清楚为什么要这么做,因为它似乎没有任何作用。

67.png

现在,调用此示例中的最后一个函数。由于这是一个相当大的函数,所以我只挑重点来说。首先,该函数会移动不同的指针,然后将加密的可执行文件的前2个字节与值0x5A4D (MZ)进行比较,以检查数据是否加密。由于它是加密的,结果不会是0,因此它将根据在嵌入式JJ结构中看到的大小分配堆。接下来,它将调用另一个函数,该函数负责执行另一个滚动XOR算法,该算法将解密数据。虽然与上一个函数有点不同,但是返回的可执行文件应该相同的。然后,它将定位PE头中的值,该值会向你透露可执行文件的系统架构,在本文的示例中是0x14C,这意味着它是基于x86的。

68.1.png

68.2.png

接下来,恶意软件将使用NtCreateSection()分配一块全新的存储部分,并将其设置为Read-Write-eXecute。此时,已解压的可执行文件就包含在其中。

69.png

此时,将形成一个位于新创建的存储区域内的地址,指向0x0022EC50,稍后将使用该地址。创建的存储部分首先会被复制到地址0x00240000。接下来,恶意程序开始将可执行文件复制到新地址,但是它会跳过整个MZ标头并简单地复制PE标头中的所有内容。

70.png

然后,调用一个从NTDLL导入更多API调用的函数,但是这次没有使用CRC哈希,并且名称只是作为参数传递。导入的API调用是LdrLoadDll,LdrGetProcedureAddress和ZwProtectVirtualMemory。指向地址的指针存储在相同的存储区域中,并被分为4个空字节。然后将这些地址复制到0x00220000处的可执行文件,以便在执行期间使用。接下来,将代码区域复制到存储中的可执行文件中,在加载的API之后只需要40个字节,以下是在完成下一个阶段之前调用的内容。

71.png

接下来,下一个函数负责将执行命令传递给可执行文件。有两个函数将执行过程传递给可执行文件,但它们依赖于系统架构。我用的是x64版本,很简单,因为它所做的只是在地址0x0022E040处调用函数,该函数将为下一阶段做好准备。因此,你可以将此阶段视为另一个“解压过程”,因为它所做的只是解压可执行文件,但是有许多函数可以延续到下一个阶段,从而使分析变得容易得多。

72.png

当我进入该函数时,会看到一个int3,它会作为一个断点来引发异常,阻止我跳过它。要解决这个问题,我可以在前一个调用上放置一个断点,重新启动调试程序,然后运行它,直到遇到断点。

73.png

因为在本文的示例中,我没有删除int3。所以,我将使用Immunity Debugger软件。Immunity Debugger软件专门用于加速漏洞利用程序的开发,辅助漏洞挖掘以及恶意软件分析。它具备一个完整的图形用户界面,同时还配备了迄今为止最为强的Python安全工具库。它巧妙的将动态调试功能与一个强大的静态分析引擎融合于一体,它还附带了一套高度可定制的纯pythont图形算法,可用于帮助我们绘制出直观的函数体控制流以及函数中的各个基本块。它负责使用以前导入的API导入DLL,首先,有一个循环将DLL名称存储在存储区域中,该名称将使用LdrLoadDll加载。然后,循环使用一组硬编码的API,每个API都传递给LdrGetProcedureAddress,加载的DLL是 NTDLL.DLL,KERNEL32.DLL和OLEAUT32.DLL。

74.1.png

74.2.png

74.3.png

导入API后,ZwProtectVirtualMemory就会在一个循环中被调用多次,以更改几个存储区域的保护。

75.png

为了跳转到有效载荷执行发生的位置,我希望在调用寄存器(在本文的示例中为EBX)时设置断点。一旦断点被触发,就表示你已经进入了ISFB攻击中的下一个阶段。

76.1.png

76.2.png

我现在需要做的就是将其转储出来,将“MZ”和“PE”添加到标头中,删除映射并使用PE Bear重新绑定它,然后我们就可以开始分析下一个阶段了!

77.1.png

77.2.png

77.3.png

转储DLL的MD5: 52b4480de6f4d4f32fba2b535941c284,至此,逆向分析 ISFB 银行木马的第一阶段的加载程序的过程已经全部完成,并解压了下一个阶段的一些内容,我将在下一篇文章中对其进行分析。

前言

Ursnif是目前活动最为频繁的银行木马,它也被称为GOZI。实际上,它是Gozi-ISFB银行木马的一个变种版本,自从该木马在2014年泄露了其源代码之后,攻击者这些年来一直都在升级和更新Gozi的功能。最近的一次版本更迭是在2019年年初,在这个变种版本中,Ursnif还嵌入了针对Office文档的攻击“武程序”,即恶意VBA宏,它可以作为Dropper或经过混淆的PowerShell脚本来隐藏真正的恶意载荷。除此之外,Ursnif还使用了隐写术来隐藏恶意代码并躲避检测。另外,这个变种还使用了QueueUserAPC进程注入技术来向explorer.可执行文件注入恶意代码,这种技术的隐蔽性更强,因为不需要在目标进程中创建远程线程。

在过去的几个月里,我一直在分析不同版本的Ursnif,以便更深入的了解其功能的演化。在这篇文章中,我将详细介绍如何解压并分析第一阶段加载程序的可执行文件,然后使用这些信息提取第二阶段加载程序DLL,即rpcrt4.dll,我将在后面的文章中对其进行分析。

简而言之,ISFB是一个银行木马,用于从毫无防备的受害者那里窃取财务信息。本文分析的ISFB样本是版本2.14.60,可以根据所使用的感染例程(特别是执行简单的Base64编码的powershell命令的宏),判断其幕后的开发团队是ISFB v2。另外,该团队还为不同的攻击活动重用加密密钥(默认密钥),与其他开发ISFB的大型团队相比,此团队更容易被识别出来。由于我一直无法找到该团队的具体名称,因此,根据FireEye的演示,我将把这个团队称为Group 53。

1.png

与其他利用ISFB获取经济利益的团队类似,Group 53使用包含嵌入式宏的恶意Word文档在目标系统上获得持久性注入,从而生成负责下载第一阶段可执行文件的Powershell脚本。而某些团队有时为了让自己开发的ISFB样本得到大范围传播,会与其他恶意传播团队合作,例如Hancitor背后的团队就是这么做的。Hancitor,也被称为Chanitor或Tordal,是一个基于宏的恶意软件,通过分布在垃圾电子邮件活动中的Microsoft Office文档传播。不过借助其他传播方式也有缺点,就是佣金过于昂贵,这就是为什么很多团队,包括Group 53,都不得不通过建立自己的传播渠道,来传播恶意文件的原因。在这篇文章中,我将重点分析ISFB样本在传播过程中所使用的可执行文件解压程序(unpacker 可执行文件cutable)和第一阶段可执行文件加载程序,而不是Word文档本身,因为它的功能非常简单。

与往常一样,样本已上传到VirusBay,需要的话,请你自行下载。

解压第一阶段可执行文件

第一阶段可执行文件的MD5:bc72604061732a9280edbe5e2c1db33b

通常我会在PEStudio(一款免费且实用的应用程序代码验证工具)中打开它或者执行一些静态分析,但是在本文的案例中,由于我已经确定它是基于Word宏的ISFB样本。首先,我会在IDA中打开它,尝试在存储区域或寄存程序中找到一个调用(或jmp),这可能是对解压阶段的调用。

2.png

基于上图中显示的长度和错综复杂的流程,看起来确实有一些解压过程正在进行。但在查看二进制文件中的字符串时,却没有看到很多有意义的字符串。 通常在解压样本时,我会从底部开始,然后逐步向上进行,大多数解压程序在文件解压后会自动退出。在本文的示例中,解压程序会执行自注入,并使用解压文件覆盖自身。这对于ISFB来说并不罕见,如果你分析一些其他样本,也会发现这种情况。这意味着解压程序在解压文件执行之前不会退出,尽管我可以假设最后调用的函数会将执行转移到已解压的可执行文件。

在刚刚的示例文件中,寄存程序或存储区域虽然没有调用或jmp,但是,却调用了loc_42A880。这是Win主中的最后一次调用,如前所述,此函数很可能负责可执行文件。

3.png

当我跳转到这个函数时,很明显它还没有被转换成功。因此,我将不得不以文本模式处理。当然,可以跟踪跳转和条件跳转来尝试找到调用或跳转到可执行文件。找到一个调用指令并单击它,可以加快调用速度。你只需从所在的位置向下或向上滚动,寻找其他调用示例。我找到的最后一个调用将lpAddress作为第一个参数,所以让我来看看这个。lpAddress表示它包含一个到存储区域的地址,这意味着它可以包含一个已解压的可执行文件的地址。

4.png

如果我直接跳到这个函数到末尾,就可以看到对ESI的调用。按空格密钥你可以从图形视图跳转回文本视图,以获取此调用的地址。这可能是对解压的可执行文件的调用,所以我需要它的地址在x32dbg中查看它并在其上放置一个断点。

5.png

所以这个调用的存储地址是0x0042A653,现在我可以在x32dbg中打开它并跳转到这个地址。只需在x32dbg中按CTRL-G并密钥入0042A653,然后按回车密钥,就会跳转到该地址,允许你在其上放置断点。在尝试解压本文的样本时,我更喜欢在同时也打开Process Hacker(一款拥有windows任务管理程序的开源软件),这样如果我在错误的地址上放置断点并执行解压的进程,你可以通过“网络”选项卡或“进程”选项卡轻松检测到该断点。

6.png

一旦断点被发现,就会进入ESI。在本文的样本中似乎是第二个解压过程,这个代码原本不在这里,事实上如果我尝试在IDA中查看它,就会看到很多问号和变量unk_58FC08。

7.1.png

7.2.png

由于很难对这部分进行静态分析,所以我将跳过该函数,而不是手动遍历它们。这也有助于加快分析速度,但前提是确保没有连接网络适配程序,因为其中一个函数可能会执行可执行文件。

在下面的GIF中,你可以看到存在某种形式的循环,其中XOR用于对存储在EAX中的存储地址进行异或运算,其值为DL。你可能还会注意到,随着每个循环的继续,程序集也会随着发生变化,不过这是第二个解压阶段的另一个示例。我可以简单地在jmp上放置一个断点,然后运行程序直到它被发现。

8.gif

一旦执行跳转,就会遇到几个对[ebx+xxxxxx]的调用。其中每一个都可以跳转到解压的可执行文件。但随着我的深入分析,很明显,这些只是对Windows API函数的调用。不知你是否注意到对EDI的调用了吗?EDI指向一个函数,该函数会动态导入这些API,以便解压存根(stub)调用它们。调用结果存储在EAX中,如下图所示,这个特定的调用导入了API RtlExitUserThread。

9.png

向下滚动一点,我可以看到一个jmp eax,所以我可以在它上面放一个断点并运行它,直到跳转完成。

10.png

这个跳转将带我进入一个新分配的存储区域,其中包含更多代码。由于我并不想检查每个函数,所以我一直向下滚动,直到找到ret指令,并开始向后检查(是本地而不是API调用)函数。最后一个函数似乎不太可能是可执行的“executor” 工具,因为没有调用或跳转到不同存储区域的指令,但是最后一个函数对[ebp+14]和[ebp+C]有一些调用,所以我会在这些函数上设置一些断点。Executor是一个比Windows“运行”功能更为强大、自定义更强的工具,如果你需要经常查找程序或者想快速运行程序这个功能比较适合你。

11.1.png

11.2.png

但是,在执行程序并触发断点时,很明显它们只是调用LoadLibrary和GetProcAddress。

12.1.png

12.2.png

由于该函数只是导入API,这对我来说并不是非常重要。所以退出该函数后,我进行了几次API调用,特别是VirtualProtect。VirtualProtect负责更改不同存储区域的权限或保护,使它们可读、可写或可执行。在本文的示例中,我可以看到VirtualProtect用于更改存储区域0x00406000的保护,即.BSS部分。正如我前面提到的,这个解压程序用解压的可执行文件进行自我覆盖。所以可以肯定的说,我已经找到解压的可执行文件了。现在我可以开始转储它们了,但可能会有一些额外的解压过程,所以我先要跳转到0x00400000存储区域。

13.png

此时,函数中还没有太多有意义的内容,因此我可以简单地在ret指令上放置一个断点,然后从退出该函数。

14.png

退出该函数后,你会注意到存储地址位于0x00401000区域。这就是用于解压的程序!现在我可以将其进行转储,因此请确保你已打开Process Hacker。

15.png

要从存储中转储它,只需双击Process Hacker中的进程,然后右密钥单击0x400000存储区域,并选择保存。

16.png

现在我可以在PEBear中打开它并删除映射转储的文件。执行此操作后,你可以看到PEBear未成功解析导入的文件。这就是我需要删除映射文件的原因。当程序即将执行时,需要将其映射到存储中,以便可以正确解释它。因此,在我删除映射之前,PEBear无法解析导入的文件。

17.png

此时,我只需更改Raw Addr,使其与Virtual Addr匹配,然后相应地更改Raw Size 。此时,你应该会看到如下图所示的内容。

18.png

检查导入的内容,果然有4个导入的DLL,这意味着我得到了正确的未映射文件。现在我可以将其保存到桌面!

至此,我就彻底成功的解压了第一阶段的加载程序!接下来,我会在IDA中打开它们,并进行进一步分析。

19.jpg

分析转储的可执行文件

转储的可执行文件的MD5: 0063316975e55c765cd12e3d91820478

在IDA中打开文件后,我可以看到主函数只调用了一个本地函数,然后就退出了,因此找到恶意代码并不困难。如果你不确定找到的示例是否是ISFB,可以在字符串窗口中找到一个提示符。大多数ISFB有效载荷会以明文形式存储用于字符串解密的编译开始日期。在此示例中,编译日期是2019年1月28日,因此在撰写本文时,它是一个相对较新的样本。在介绍字符串解密方法之前,首先让我们看看在函数中发生了什么。

20.1.png

20.2.png

在这个函数中有很多个函数被调用,让我们先看一下前四个函数。从下图可以清楚地看出,sub_401C69(存储在eax中)的返回值需要与esi中的值匹配,否则它将跳转到出口。第二个函数sub_401E4F似乎也与它类似。第三个函数似乎是检查某些内容的,第三个函数似乎是检查某些东西的,因为根据 bit-wise AND(一种利用bit-wise索引进行查找的方式)在eax上的检查结果,1会被移入DWORD。第四个函数似乎以与第一个和第二个函数相同的方式运行,即将返回的值与esi中的值进行比较,如果不满足条件,它将自动退出。

21.1.png

21.2.png

看看第一个函数(主位),我可以看到恶意软件正在打开它自己的进程并将句柄存储在DWORD中。如果恶意软件无法打开该进程,则将其设置为-1,然后返回主函数,返回的结果与ESI中的值进行比较。

22.png

第二个函数则非常有趣,在下图中,你将注意到编译日期被移动到ESI中,正如我之前提到的,编译日期被用于字符串解密。由于ISFB包含.BSS部分,其中包含多个使用ROR-XOR算法加密的字符串。XOR密钥是根据给定日期计算的,为了解密字符串,ISFB需要再次执行计算以获得正确的密钥,这样我就可以轻松地进行逆向分析。但首先,我来看看事先调用的两个函数。

23.png

看看第一个函数,你会注意到 ssb(实际上是.BSS)与循环内的[ECX]的值进行比较。为了解密.BSS部分中的字符串,ISFB必须首先找到.BSS部分。为了做到这一点,它只需读取自己的PE标头并获取所需部分的大小和地址。如果[ECX]处的值与.BSS不匹配,则在ECX中的存储地址添加40,这是因为段描述符或结构(.text,.data等)之间的间距为40字节。此时,循环将继续。如果匹配,则检查字符串的长度,确保它不超过4个字节。恶意软件通过检查字符串后面的字节并将其与零进行比较来完成匹配操作,如果字符串的长度正确,则指向“.BSS”的存储地址将被移入EDX。如果一切顺利,ISFB将获取.BSS部分的地址和大小,并将其存储在存储中。在本文的示例中,地址是0x6000,大小为0x1000。如果这仍然很难理解,那么请看下面我在x32dbg中的截图,这应该可以帮助你了解它是如何获取地址和大小的。

24.1.png

24.2.png

函数:sub_401C0F # 2

25.png

下一个函数的主要目的是使用AddVectoredExceptionHandler添加一个向量异常处理程序,其中第二个参数是指向处理程序函数的指针,该函数将在程序运行到异常时执行,因此让我们看看exception tion_handle_function函数。

26.png

此函数会检查异常的值,无论值是EXCEPTION_ACCESS_VIOLATION还是EXCEPTION_SINGLE_STEP,它们最终都会执行相同的函数,所以进入该函数来看看。

27.png

该函数的重要功能会在函数执行后很快发生,在下图中就是我创建的一个循环,以及两个XOR指令和一个ROR指令。稍后创建的XOR密钥实际上是arg_8,请注意这一点。现在我可以确定会某个时候会有一个异常,且会执行BSS字符串解密函数。有了这些信息后,我可以转而从编译日期开始逆向分析恶意软件是如何创建XOR密钥的?

28.png

由于XOR密钥基于日期创建的,因此我需要查看日期。首先,将BSS部分的地址(0x6000)移入EAX,并将其大小(0x1000)移入EDX。然后,将编译日期的存储地址移入ESI,并将该地址(指向存储的空白部分)移入EDI。然后使用MOVSD将编译日期移动到存储的空白区域,MOVSD会将一个DWORD从ESI中的存储地址移动到EDI中的存储地址,接下来,将编译日期的第一个DWORD移动到ECX中,并对编译日期的第二个DWORD执行XOR运算。接着,将其结果添加到BSS部分的地址(此处为0x6000)和值0xE中,然后将其作为将被调用的下一个函数的第一个参数推送。

29.png

在下一篇文章中,我会接着分析剩余函数和它们对应的加载过程。

cyber-telecom-tower-200x200.jpg

电信技术是现代网络的基础,随着网络技术的发展,细分出了类似物联网(IoT)这样的新形态。这意味着,我们今天享有的全球电信网络也反过来受到网络发展的极大影响。电信和网络之间的关系和界限越来越模糊,普通用户甚至无法区分它们。我们都经历过这种情况,比如我们订购的电信运营商与我们连接的网络运营商非常相似甚至是一家公司。这种情况随着5G时代的来临,会成为常态即电信运营商就是你的网络运营商。在趋势科技与欧洲刑警组织欧洲网络犯罪中心(EC3)共同发布的《2019年网络电信犯罪报告》中,他们探讨了如何利用这种关系来对物联网和5G进行电信犯罪。

SIM卡连接

众所周知,通信设备和网络设备是使用SIM卡进行连接的。所以要让物联网设备既做到独立存在,又能与网络连接,它们应该像手机一样安装一张SIM卡。这可能是我们熟悉的白色SIM卡,或者更小的附着在设备电路上的东西。总之不管是手机的SIM卡还是物联网设备的SIM卡,它们的功能就是拨打或接听电话、发送短信或数据。

SIM卡可以像信用卡或借记卡一样使用,因为它们被用来启动计费或连接,并收取相应的费用,这就是为什么对SIM卡的欺诈攻击会和信用卡一样多的原因。此外,因为电信行业没有受到洗钱控制的监管,所以对SIM卡的攻击才比较猖狂。

对于智能城市设备,如交通信号灯和智能垃圾箱,网络犯罪分子可以采用多种方式滥用SIM卡。他们可以选择提取嵌入在物联网设备中的SIM卡,并使用SIM来洗钱或进行其他非法活动。在某些情况下,即使SIM卡难以被提取,漏洞仍然存在于设备中,以待时机成熟随时发起攻击。

分组订阅聚合(Bucketed subscription aggregation)也是物联网的一个问题,特别是在智能城市等更复杂、更大规模的物联网环境的开发中。这样的规模可能会遇到安全措施不足的问题,许多物联网设备(多达数百万)被聚合到一条信道上。这就意味着,这些物联网设备中即使有SIM卡受到攻击,由于监管不足,它所引发的欺诈行为也不会被发现。

同样重要的是要注意,即使物联网设备是“哑”的,没有打电话或发送消息的能力,但这并不意味着其SIM卡也受到限制。不幸的是,许多大规模物联网的采购部门通常忘了SIM卡可能拥有未知的电信功能,可能被网络犯罪分子用于数据恶意软件感染或远程欺诈。

fig-8-01-440x286.jpg

物联网SIM流程中的攻击模型

大型物联网基础设施

但对于电信诈骗犯来说,可扩展性是这也是一个攻击机会。根据部署的物联网设备的数量和专用服务器等支持技术,其环境可以从一个家庭扩展到整个城市。规模越大,监控每个连接设备的难度就越大。

即使是较小规模的环境,如智能家居,建筑物和工厂,也存在着被用于电信欺诈的风险。虽然智能工厂通常与外网相隔离,但它们仍然需要某种形式的蜂窝数据连接来执行远程备份或进行远程维护。通过这种连接,网络犯罪分子可以利用网络电信漏洞对目标进行攻击和欺诈。

即使是智能和自动驾驶汽车也可能受到与手机相同的攻击。例如,电话拒绝服务(TDoS)可能会导致智能汽车因网络连接中断而丢失。

如何预防针对物联网和5G的电信犯罪

了解了物联网和电信之间的联系,以及可能存在的攻击风险,应该有助于建立防御威胁的机制。掌握物联网设备使用的公共信道可以发现隐藏的电信功能,对于物联网设备来说,更改默认设置和设备登录凭据等简单措施已经可以防止一些上述的电信攻击了。

电信技术和物联网的融通已经证明,互联互通可以成为一种强大的工具,可以帮助我们节省时间,提高办事效率并减少连通壁垒等。 然而,这种便利可能会被滥用。

对基础设施的攻击不只是诈骗获取经济利益那么简单,甚至可能被用于战争

网络对现在社会发展的关键作用已经不可替代,大到军事、政治小到微商,我们已经离不开它了。以网络犯罪的攻击力量和多样性来看,把它升级为网络战争不是不可能的。

近年来,国家支持的黑客行动已越来越明显,这种形式的犯罪通常都是采用网络间谍的形式试图窃取政府人员或昂贵的防御项目的数据。而支持这些黑客的政府会花费数百万美元用于躲避其他国家的安全监测,然后对对方的国防承包商或关键国家基础设施的系统进行监测,通常这些黑客行动要发展许多年。

像黑客活动分子一样,国家支持的黑客团体通常不寻求经济利益,比如通过揭露其他国家的丑闻来寻求本国的战略优势。俄黑客组织APT28就对美国总统大选造成了干预,至今特朗普还面临着竞选作弊指控。

可见随着网络威胁的不断升级、网络攻防对抗的日趋激烈,许多国家已经认识到塑造网络空间、保障网络安全是强化国家竞争力和维护国家安全的重大战略问题。现在美国已经把将网络空间列为与陆、海、空、太空并列的“行动领域”。

如果国家支持的黑客把对手国的电网功率给降低或是进入工业系统中枢把水坝的大门强制打开,那这就由网络犯罪升级到了网络战争。

今年的3月7日,委内瑞拉首都加拉加斯及其他数个城市在当地时间7日晚突然停电,总统马杜罗当天发声,指责美国对该国发动“电力战”。 据统计,委内瑞拉超过全国一半地区完全停电,且持续超过6小时。此次停电是自2012年以来委时间最长、影响地区最广的停电。

随后,马杜罗在推特上发文指责美国,称这是“美帝国主义”发动的“电力战”。他还补充说,“没有任何事、任何人能打败委内瑞拉”。

如果马杜罗说的是事情,则这次停电事故是美国精心策划的 “电力战”。其实这种战争以前并不是没有发生过,2006至2010年,著名的震网病毒曾经入侵伊朗核工厂长达五年之久,严重破坏了伊朗核计划。那次入侵的战场只在网络之间,武器也只是软件程序,但它却完全符合最严格的战争定义:它发生于国家之间,它针对军事设施和人员,它企图达到某种政治目。因此,震网病毒被认为是人类第一场网络战争,也就是说我们早在2006年就已进入网络战争的时代。

2008年8月,正当举世瞩目的奥运会在北京开幕之际,俄罗斯和格鲁吉亚因南奥塞梯问题兵戎相见,引发了震惊世界的俄格冲突。在俄政府出动军队进行地面和空中作战的同时,一些俄罗斯民众组织了对格鲁吉亚的网络攻击。这次网络攻击威力巨大,效果显著,使格鲁吉亚政府和 新闻媒体的网站几乎全部陷入瘫痪,无论在格境内还是境外都无法访问。西方军事专家认为,俄罗斯 在俄格冲突中不仅赢得了军事上的胜利,而且取得了心理战和舆论战的胜利。格鲁吉亚无法利用网络发布有关作战情况的准确信息,同民众进行有效沟通,而俄罗斯 则在战争中赢得了国内外舆论的支持。

反观此次美国对委内瑞拉发动的“电力战,就是网络攻击的结果。考虑到美国政府对委内瑞拉局势的长期关注,美国势力已很可能渗透进了委内瑞拉关键的基础设施网络中,而委内瑞拉陈旧的网络和电力设施对这种干扰操作毫无抵抗之力。

具体的攻击步骤可能是以下3步:

1.渗透进委内瑞拉关键的基础设施网络中,植入恶意代码并在适当时候运行它们;

2.通过无线入口进行目标渗透;

3.利用互联网通道直接攻击,目前电网和互联网有着千丝万缕的链接,完全可以通过最常规、典型的网络攻击步骤,攻击进入委内瑞拉电力系统。

随着物联网的出现,从恒温器到家庭安全系统的日常用品都可以被网络操控, DDoS就说明了问题。如果您的组织正在受到来自国家支持的黑客攻击,那么保护它们可能非常困难了。

在现实中,以上这些不同的黑客团体的身份往往是多重的,FireEye的Monrad说:“网络威胁形势正变得日益严峻和复杂。”可以肯定的是,我们的日常生活对互联网有多依赖,那网络犯罪的潜力就有多大。

顾名思义,多租户就是很多人来租用容器平台的资源来实现自己的应用托管运维需求。有了资源,那么谁来管理运维分配使用这些资源?多租户很重要的一点是资源的安全隔离。即便是专用容器,也需要考虑相应的安全和业务隔离需求。

从多租户的角度考虑,租户租用容器云平台的资源来托管、开发、部署运维自己的应用、服务。容器云平台需要提供、维护保障租户能正常使用这些资源,同时给租户托管的应用提供服务注册、服务发现、服务配置、日志、监控、预警告警、弹性伸缩、负载均衡、安全等能力。我们要明白的是租户只是租用这些能力,他们并不负责维护。

那么谁来管理运维分配使用这些资源?那么容器云中什么是资源?资源该由谁来管理?如何分配?谁来运维这些资源?谁来使用这些资源?这也是我写本篇文章的目的,本文包含了我对一般多租户安全容器协调器的详细安全考虑。我会通过具体示例来讲解如何在隔离状态下,安全的运行第三方代码,详细介绍请点此

测试环境的配置

1.用于运行Docker镜像的API,使每个进程完全与其他进程隔离;

2.滥用行为可以立即终止;

3.代理应该是可自动更新的,以便在出现安全问题时处理它们;

4.能够将整个syscall接口用于正在运行的进程;

配置性能要求

1.禁止并删除任何挖矿工具所使用的基础设施及追踪器;

2.防火墙可以关闭任何现有网络端点;

3.防火墙可以将运行该进程的容器与它相关联的所有本地链接和任何可访问的内部IP隔离开来;

4.如果一层多租户容器间安全隔离受到破坏,则另一层隔离需要马上跟上。如果两层安全隔离同时受到破坏,那么还会有隔离机制用于保护;

5.主机操作系统要是安全的;

测试过程

我们要求每个容器按照如下条件运行:

1.Block/io cgroups,以便磁盘没有噪声干扰。Cgroups是control groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO等等)的机制。最初由google的工程师提出,后来被整合进Linux内核。

2.CPU限制;

3.内存限制;

4.网络或带宽限制;

5.有一个与测试主机的其他网络相隔离的网络(bpf或iptables);

主机操作系统

主机操作系统应该是一个简化的操作系统,具备最简单的功能即可,即尽可能与容器内使用的操作系统共享许多功能。这是为了将主机环境中的运行漏洞降到最低,减少攻击面。

这些操作系统的示例包括:

1.配备 CoreOS的 Container Linux ;

2. Container Optimized OS;

3.Intel Clear Linux, 英特尔推出Clear Linux项目的目标是让用户可以充分利用虚拟机的隔离技术以及容器的部署优势;

4.LinuxKit, linuxkit这个工具可以理解为是用多个docker镜像来组成一个最小化、定制化的操作系统,定制化后的系统只有几十兆;

主机操作系统的特征

CoreOS Container Linux和Container Optimized OS都具有以下功能:

1.验证启动;

2.只读或 usr:

2.1Container Optimized OS会将根文件系统(/)挂载为只读,并将其某些部分重新挂载为可写;

2.2/tmp, /run, /media, /mnt/disks 和 /var/lib/cloud都是使用tmpfs挂载的,虽然它们是可写的,但它们的内容在重新启动之后是不会保留的;

2.3目录/mnt/stateful/partition, /var和/ home是从有状态的磁盘分区挂载的,这意味着这些位置可用于存储在重新引导后持续存在的数据。例如,Docker的工作目录/ var / lib / docker在重新启动时是有状态的;

2.4在可写位置中,只有/var/lib/docker和/var/lib/cloud被挂载为“可执行”,即没有noexec挂载标志;

2.5CoreOS Container Linux的根文件系统(/)挂载为read_write,而/ usr是只读的;

3.所有操作系统都允许无缝升级以解决安全问题;

容器运行

容器运行时应该是一个管理程序,以确保Linux容器的用户配置不会降低集群的安全性。

如果要允许使用整个系统调用接口,Firecracker似乎是最合适的。Firecracker是一种专门用于创建和管理多租户容器和基于函数的服务的虚拟化技术,使用Rust开发,旨在加快AWS Lambda和AWS Fargate等服务的速度和效率。

网络要求

默认情况下,网络应该被锁定,拒绝所有入口和出口策略。这将创建一种安全形式,确保网络环境的绝对安全。

这可以通过iptables或直接使用BPF来实现。

DNS

不允许任何inter-cluster DNS,在主节点和系统节点上没有调度:确保集群中的主节点和系统节点不能被调度,这允许将系统进程的重点转移到其他地方。

调度程序

调度程序不应该对bin文件进行打包,在许多使用临时工作载荷的场景中,当前几个节点耗尽而所有其他节点都没有被使用时,会出现这种情况。因为工作载荷不断地完成释放前几个节点上的资源(在批处理作业的情况下)。

Kube-batch目前是Kubernetes SIGs旗下的一个孵化项目,是一个运行在 Kubernetes 上面向机器学习 / 大数据 /HPC 的批调度器(batch scheduler),它支持以 Pod Group 为单位进行资源调度,并支持preempt和priority。对于暂时无法满足资源条件的Pod,在Kubernetes中会处于pending状态,直到资源释放从而继续执行。Kube-batch是基于IBM多年的HPC集群经验构建的,它更适合批处理作业,因此如果我们打算长期应用此程序,就需要对其进行修改。

如果我们在裸机上运行,我们需要考虑电源管理、BIOS更新、硬件故障等等。

资源约束

使用cgroup管理资源并设置限制:

1.磁盘IO;

2.网络带宽;

3.内存;

4.CPU;

避免被挖矿

1.带有eBPF的CPU跟踪器会监控CPU使用率,因此如果它没有波动,则它可能是一个挖矿工具;

2.二进制跟踪器负责查找具有特定名称的二进制文件或进程;

3.网络跟踪器负责寻找与已知挖矿工具端点相关的进程;

为什么不用kubernetes?

kubernetes,简称K8s,是用8代替8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。

由于我不希望任何允许任意代码执行的容器只有一层安全保护,所以我认为kubernetes很难满足这个要求。

Kubernetes的etcd集群之间没有隔离,而且kubelet与apiserver的通信也不能被隔离。Etcd是Kubernetes集群中的一个十分重要的组件,用于保存集群所有的网络配置和对象的状态信息。

总而言之,Kubernetes太复杂了,有太多的第三方驱动程序。攻击面太大,我们不需要其中的大部分(90%)功能设置。

默认情况下,Kubernetes将为每个节点安排最多110个pod。这是你可以修改的方面,但同样重要的是要注意kubernetes中的默认调度程序是无法识别资源的,我们必须对其进行修复。具体的请参阅上面的“调度程序”那一节,由于默认调度程序的逻辑,集群中的前几个节点会破坏。

甚至谷歌内部也不使用Kubernetes来调度虚拟机,Kubernetes在容器中插入了一些额外的env变量,我们也需要处理这些变量。

如果存在影响隔离的内核零日漏洞,我们该怎么办?

首先,更新内核,但如果内核更新不了,我们可以使用ebpf捕获易受攻击的内核函数,并删除任何试图利用漏洞的容器。

假设我们已经有了可以持续构建内核和应用补丁的系统,则可以考虑威胁模型。大多数情况下,有人会攻击我们的基础架构,因此我们应该确保所有这些服务器在网络上与其余堆栈隔离。

另外一个威胁是我们正在运行的用户名和密码在打开容器之后,黑客会通过VM截取它们。一般来说,容器运行错误时就会发生这种情况。

在用户高峰时段,常用的移动网络很容易堵塞,不堪重负。所以,关键时刻能够建立安全可靠的通信,是非常重要的。在本案例中,我用的移动通信系统是GSM协议,为了能够将GSM协议广播出去,我使用了BladeRF。

需要的设备

1.树莓派,本文使用的是树莓派3;

2.Micro SD卡,本文使用的是32 GB的;

3.Nuand BladeRF,本文使用的是BladeRF x40;

4.在树莓派上启用SSH,为了便于使用,终端也可以正常运行;

5.一部兼容GSM和SIM卡的手机;

6.SIM卡(sysmoSIM-GR2);

7.一根网线;

树莓派的设置

译者注:BladeRF是由树莓派使用YateBTS控制的,YateBTS是实现手机访问网络和GSM核心功能和协议的软件,允许手机通过语音、文本和数据进行通信。

1.将网线、电源和键盘插入到树莓派中,然后将电源适配器通电。注意:在树莓派中默认的用户名为pi,默认的密码为raspberry

2.开始运行;

sudo raspi-config

键盘布局进行合理化布局

1.找到“本地化选项”,按“Enter”键;

2.找到“更改键盘布局”,按“Enter”键;

3.找到“Other”,按“Enter”键;

4.找到“英语(美式)”,按“Enter”键;

5. 找最上面的“英语(美式)”,按“Enter”键;

6.点击“进入”,接受下面两个屏幕上的默认值,因为它们不适用。

7.完成最后两步后,返回到主菜单。

启用SSH

1.找到“接口选项”,按“Enter”键;

2.找到“SSH”,按“Enter”键;

3.找到“Yes”,按“Enter”;

4.在下一个屏幕上,按“Enter”键返回主菜单;

5.进入主菜单,选择“完成”,然后按“Enter”;

6.返回终端时,运行下面的命令来启用配置设置;

sudo reboot now

网络部署过程

为了在设置好的树莓派上启用SSH,请使用以下命令记录Pi的IPv4地址:

ifconfig eth0

然后在另一台计算机上,利用终端应用程序运行:

ssh [email protected][INSERT PI IPV4 ADDRESS HERE]

一旦出现证书的提示,就必须再次输入用户名pi和默认的密码raspberry。

现在你就可以与Pi进行远程交互了:

# Download the script from GitHub
wget https://raw.githubusercontent.com/MBRO95/PortableCellNetwork/master/PortableCellNetwork.sh
# Make the downloaded script executable 
chmod +x ./PortableCellNetwork.sh

首先,脚本会检查你是否是以root身份运行的,因此请确保你必须输入以下命令的“sudo”部分。

在不记录输出的情况下运行脚本:

sudo ./PortableCellNetwork.sh

在记录输出的情况下运行脚本:

sudo ./PortableCellNetwork.sh | tee install.log

1.该脚本将查询网络名称,你需要按“Enter”键接受“DuaneDunstonRF”的默认名称或提供一个能够确认的信息;

2.确认网络名称;

3.该脚本现在将启动安装和配置过程;

4.当脚本启动快完成时,它将查询“pi”用户的新用户密码。此时,你需要重新输入密码,以加强安全性。

当完成脚本启动时,它将报告运行的时间并等待重新启动输入。

1.按任意键重新启动,这样你将被重新被引导到桌面环境中,此时,你只需在启动的弹出窗口中选择“默认配置”选项。

2.一个名为“StartYateBTS”的启动脚本将出现在 ‘/home/pi’ 中,并开始启动移动网络进程。不过要启动脚本,必须在出现脚本名称后通过发送一个“- i”标志以交互方式运行,“- i”标志如以下所示:

sudo ./StartYateBTS.sh -i

开始启动后,脚本将会出现以下两个运行状态:

1.打开一个终端窗口,报告Yate(移动网络)状态

2.打开一个Firefox浏览器窗口,该窗口将被导航到YateBTS(基于web的移动网络配置)。此时,你就可以查看或修改网络配置的设置了,并管理或编写设备的SIM卡。

便携式移动网络的的搭建

要将兼容GSM和SIM卡的手机连接到移动网络,需要部署SIM卡以配合正确的设置。YateBTS使用的是PySIM工具。在安装脚本时,我已经把PySIM设置为支持sysmosim-gr2卡的正确版本。不过前提是确保兼容的SIM卡编写器已经被插入到了树莓派中,并将SIM卡置于它的进程中。

现在,你就可以打开名为Manage SIM的选项卡,确保生成的随机IMSI设置被选中,注意插入用户不需要被选中。如果你不小心选中插入用户的选项,则移动网络可能将受到干扰。

9.png

接下来是检查在“高级”选项中是否进行了正确的设置,因为确保移动网络选择设置是正确的。否则,使用默认设置并点击保存。

10.png

下图就是对SIM重新编程后的输出,切记,在管理SIM的列表中对SIM卡进行部署。

11.png

在将SIM卡插入GSM手机后,YateBTS将会发送一个回应信息,并显示如下所示的手机号码。如果Android手机没有正确连接到手机网络,请打开拨号器应用程序然后输入##4636## A,此时,设置菜单将出现在手机信息选项卡中。接着请讲网络类型选为GSM,然后重新启动手机。

360截图1651100194145106.jpg

移动网络的安全保障

我安装的脚本都是基于Internet安全中心(CIS)的安全模型,该脚本集成了为Debian 8操作系统设计的基准模型,会让移动通信的安全得到最有效的保护。其实一开始,我是以树莓派的安全标准来进行安全设置的。但后来,我发现它不支持可以实现安全控制的自定义分区,但安全脚本不但可以保护各种控件,同时也能保护莓派操作系统和Yate软件的功能。

另外就是随时更新操作系统:

sudo apt-get -y dist-upgrade

linux sticky bit 目录权限的设置,这样做可以防止未经授权的用户修改或重命名属于不同用户的文件:

df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod o-t

删除不必要的文件系统:

echo "install cramfs /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install freevxfs /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install jffs2 /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install hfs /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install hfsplus /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install squashfs /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install udf /bin/true" >> /etc/modprobe.d/CIS.conf

删除不必要的网络协议:由于linux内核能支持不常用的网络协议,而这些协议又与本次的目标无关,因此,它们应该被禁用。

echo "install dccp /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install sctp /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install rds /bin/true" >> /etc/modprobe.d/CIS.conf
echo "install tipc /bin/true" >> /etc/modprobe.d/CIS.conf

禁用核心转储,以防应用程序崩溃。

echo "* hard core 0" >> /etc/security/limits.conf
echo 'fs.suid_dumpable = 0' >> /etc/sysctl.conf
sysctl -p
echo 'ulimit -S -c 0 > /dev/null 2>&1' >> /etc/profile

禁用不需要的服务,以防止这些服务被开启。

systemctl disable avahi-daemon
systemctl disable triggerhappy.service
systemctl disable bluetooth.service

众所周知,Pi为默认密码,所以切记更改树莓派的原始密码。

passwd pi

测试环境的搭建

共享文件路径的目录

/usr/local/share/yate

进入conf文件路径的目录

/usr/local/etc/yate

进入用户文件路径的目录

/root/.yate

模块路径的目录

/usr/local/lib/yate

如何测试

1.Yate NIB设置中包括一个ELIZA聊天软件,你可以把SMS消息发送到35492与该软件进行测试通信。

2.利用Android手机的配置菜单,拨打4636 # # # #测试通信。