厚客户端渗透介绍(四):程序集测试 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

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

DarkEye 技术 2020-06-23 11:20:00
753064
收藏

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

厚客户端渗透介绍(一):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位的程序集。不过,该可执行文件没有进行签名:

1.png

反编译

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

dnSpy

JustDecompile

.NET Reflector

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

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

信息泄露

托管代码

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

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

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

2.png

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

3.png

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

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

4.png

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

5.png

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

6.png

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

7.png

非托管代码

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

修改程序集

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

8.png

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

9.png

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

10.png

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

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

11.png

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

12.png

混淆

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

下面的代码是上面提到的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/如若转载,请注明原文地址:
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2024 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务