欢迎访问Sunbet,Sunbet是欧博Allbet的官方网站!

首页Sunbet_新闻事件正文

厚客户端渗透介绍(四):程序集测试

admin2020-06-2323技术

厚客户端渗透介绍(一):GUI测试

厚客户端渗透介绍(二):网络测试

厚客户端渗透介绍(三):文件系统和注册表测试

厚客户端渗透测试介绍是一个系列博客文章,上一篇我们讲到了文件系统和注册表的测试,这一章我们来看看程序集的测试。

示例应用下载地址:BetaFast Github repo。

已发布文章

· GUI测试

· 网络测试

· 文件系统和注册表测试

程序集控制

我们在编译库和可执行文件时,可以采取一些安全措施来防止代码被利用:

· 地址空间布局随机化(ASLR)—应用程序在加载时,在内存中的地址是随机的,这样可以防御return-to-libc攻击,这种攻击手法可以通过覆写特定地址导致命令执行。

· SafeSEH—将安全异常处理函数存储到二进制文件中,防止攻击者在调用恶意的异常时强制应用程序执行代码。

· 数据执行保护(DEP)—内存区域标记为不可执行,防止攻击者在这些区域存储代码来执行缓冲区溢出攻击。

· 代码验证/强命名—程序集可以通过签名来进行保护。如果没有签名,攻击者能够修改并替换为恶意内容。

· 控制流防护(CFG)—ASLR和DEP的扩展,用于对可执行代码的地址进行限制。

· HighentroyVA—64位ASLR

我们的安全研究人员发布了一款工具PESecurity,这款工具可以检测二进制文件是否使用了代码执行防御技术。我们测试的很多厚客户端程序中,它们的安装目录中都使用了程序集,文件数量很多,而PESecurity可以检测大量的文件,对我们测试非常有帮助。

在下面的例子中,我们用PESecurity来测试一下BetaBank.exe。它采用了ASLR和DEP防御技术。SafeSEH只适用于32位的程序集。不过,该可执行文件没有进行签名:

反编译

反编译是测试厚客户端程序时我最喜欢最常用的一种技术。我以前写程序时也犯了很多编程错误,因此找其他程序员的错误是很爽的一件事情。借助下面这些工具,可以将.Net程序集还原成源代码:

dnSpy

JustDecompile

.NET Reflector

这是因为.Net程序集是托管代码。当一个.Net程序被编译时,它会被编译成一个中间语言代码。只有在运行时环境中,中间语言代码会被编译成机器码。.Net程序集很容易被还原成源代码,因为中间语言包含了很多信息,比如类型和名称。

非托管代码,如C或者C++,它们直接编译成二进制。不像C,一样通过公共语言运行库环境来运行,而是直接加载到内存中。

信息泄露

托管代码

下面的案例将使用BetaBank.exe这个程序,可以在我们的github上找到该程序。这里我们也会用dnSpy作为我们的反编译器。

我一般测试厚客户端时,第一件事就是查找是否存在敏感信息硬编码,比如凭证,加密密钥和连接字符串等。查找敏感信息甚至都不用进行反编译,查找敏感信息最好的方式当然是先按配置文件。当一个.net程序集运行时,它会搜索配置文件来查找在二进制文件中引用的全局值,如连接字符串,web端点,或者是密码。这里推荐一款工具,Procmom,还有上一篇文章中提到的方法和步骤,能够有效的识别这些文件。

在这个例子中,我们在BetaBank程序的配置文件中找到了一个连接字符串。借助工具SQL Server Management Studio可以直接连到数据库中。

10.2.2.55是我运行docker的虚拟机ip:

不过对于源代码中的信息泄露,首先我们需要反编译程序的二进制文件。

如下图,用dnSpy加载BetaBank.exe程序:

dnSpy的搜索功能非常强大。我只要输入关键词”key”,”IV”,”connection”,”password”,”encrypted”和“decrypt”,就可以查找程序是如何处理加密,身份认证和数据库连接信息。软件的搜索功能中还有一个筛选器。下面,我限定了只搜索指定的文件,当然,也可以限定只搜索特定的二进制文件和对象类型。在BetaBank程序中,好像找到了一个硬编码密钥,在BetaBank.ViewModel.RegisterViewModel和 BetaBank.ViewModel.LoginViewModel模块中:

搜索“password”,找到一个硬编码的加密密码。显然,开发人员在客户端上进行授权检查。用户名”The_Chairman”直接与用户名输入框中的值进行比较,而加密的密码也是直接与密码输入框中密码的加密值进行比较。

BetaEncryption这个类可以进行反编译,可以看到一些自定义的加密逻辑:

非托管代码

前面也提到过,在测试非托管代码时,我们是无法如此清晰的查看到源代码的。为此我们看了微软Azure的CTO的推特,发现了一款工具Strings。Strings也已经包含在Sysinternals工具包里了,这个工具可以输出存储在可执行文件中的字符串列表。当分析内存转储或者是非托管代码的二进制文件时,我会用它来获取所有字符串的列表(虽然大部分的字符串都是没有意义的),然后在这一堆字符串列表中搜索上面提到的关键词。

修改程序集

使用dnSpy,我们可以修改一个类,也可以重新编译二进制文件。下面的例子中,我已经逆向了加密函数,当用户通过身份验证成功登录到应用程序时,我会用一个弹窗来显示已经解密的管理员密码,代码修改如下:

将模块另存为一个新的可执行文件:

最后,当我以某用户身份登录时,弹窗显示了“The_Chairman”的明文密码:

在进行信息收集时,在程序中添加弹窗是非常有用的,这就像是我在代码中添加一条print语句,而不是开启调试模式。

BetaBank开发人员可能会通过移除硬编码加密密钥来修复这个漏洞,然而,作用不大,因为BetaBank自定义的加密逻辑依然可以被逆向分析出来,然后获得解密的密钥。下面,我添加了一个函数,对明文密码和加密密码进行异或处理,然后公开加密密钥。在解密函数中,我通过传递一个已知的明文密码及其加密值来获取密钥:

但是那样工作量有点大。如果我们后面不需要“The_Chairman”的密码,可以直接把用户名和加密的密码放到login函数中。布尔逻辑也可以修改,这样任何经过服务端验证的逻辑,比如IsAdmin(),可以修改为始终返回true。

混淆

源代码也并不总是清晰可读的,有时候,源代码是经过混淆的。虽然混淆并没有什么安全性可言,   但还是给安全人员阅读代码增加了不少麻烦和难度。

下面的代码是上面提到的BetaEncrypted类,不过我添加了一些混淆,重命名了类型,方法名和参数名:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public static class jinjnhglkjd
{
    public static string dsfggd(byte[] erttr, string dgfhfgi)
    {
        byte[] plaintextBytes = Encoding.ASCII.GetBytes(dgfhfgi);
        byte[] ciphertextBytes;
        int messageLength = plaintextBytes.Length;
        while (messageLength % erttr.Length != 0)
        {
            Array.Resize(ref plaintextBytes, plaintextBytes.Length + 1);
            plaintextBytes[plaintextBytes.Length - 1] = 0x00;
            messageLength += 1;
        }
        ciphertextBytes = new byte[messageLength];
        int startingIndex = 0;
        for (int i = 0; i < (messageLength / erttr.Length); i++)
        {
            for (int j = 0; j < erttr.Length; j++)
            {
                ciphertextBytes[j + startingIndex] = Convert.ToByte(plaintextBytes[j + startingIndex] ^ erttr[j]);
            }
            startingIndex++;
        }
        return Convert.ToBase64String(ciphertextBytes);
    }
}

所有的功能都正常,而且能够正常运行。有些混淆技术做的更深入,直接混淆代码,让代码变得不可读。这些技巧会让我们在源代码中搜索关键词或者你想变得十分困难。dnSpy软件的程序集资源管理面板显示的都是毫无意义的类名,搜索特定的关键词如“Encrypt”,也没什么结果。

当然,也有很多反混淆的工具,比如de4dot。下面的代码就是用这款工具进行反混淆之后的,至少类名有一些可读性,方法名也命名为了method的一些变形,而不是dsfggd这些乱码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public static class class_1
{
    public static string method_1(byte[] byte_1, string string_1)
    {
        byte[] plaintextBytes = Encoding.ASCII.GetBytes(string_1);
        byte[] ciphertextBytes;
        int messageLength = plaintextBytes.Length;
        while (messageLength % byte_1.Length != 0)
        {
            Array.Resize(ref plaintextBytes, plaintextBytes.Length + 1);
            plaintextBytes[plaintextBytes.Length - 1] = 0x00;
            messageLength += 1;
        }
        ciphertextBytes = new byte[messageLength];
        int startingIndex = 0;
        for (int i = 0; i < (messageLength / byte_1.Length); i++)
        {
            for (int j = 0; j < byte_1.Length; j++)
            {
                ciphertextBytes[j + startingIndex] = Convert.ToByte(plaintextBytes[j + startingIndex] ^ byte_1[j]);
            }
            startingIndex++;
        }
        return Convert.ToBase64String(ciphertextBytes);
    }
}

混淆并不能保护代码,但是阅读源代码时会让人头疼,甚至比读其他人的大型代码库还令人头疼。

本文翻译自:https://blog.netspi.com/introduction-to-hacking-thick-clients-part-4-the-assemblies/:
已经运行了四年多的安全防护产品CloudEyE竟然包含GuLoader程序

2019年12月,网络安全公司Proofpoint的研究人员发现了后来被他们命名为“GuLoader”的新型恶意软件下载器。在当时,虽然GuLoader是恶意软件下载器家族中的新成员,但GuLoader很快便得到了广泛应用,被大量的网络黑客用于传播远程访问木马以及信息窃取程序,包括Agent Tesla/Origin Logger、FormBook、NanoCore RAT、Netwire RAT、Remcos RAT和Ave Maria/Warzone RAT等。GuLoader是一个使用VB语言编写的恶意软件下载器。它通常从Google Drive、Microsoft OneDrive、MediaFire等托管站点下载恶意代码执行。常见的后续恶意远控程序有:LokiBot、Remcos RAT和Agent Tesla等等。GuLoader本身具有较为复杂的执行流程,较强的反调机制使得当前部分在线沙盒无法精确检测恶意行为,同时也给分析人员造成一定阻碍。今年

网友评论