登陆 注册

CS Powershell Beacon分析

桑云信息Lzers 2021-08-25 CobaltStrike安全文摘

前言

这里分析的为Cobalt Strike的Powershell Beacon Payload 

主要目的为方便更好免杀和学习一下样本分析。

代码不多,可以看到主要分为3个部分

第一部分

我们从主入口IF部分开始分析:

[IntPtr]::size -eq 8

这里返回一个True

[IntPtr]::size的功能为获取当前的powershell环境为x86还是 x64

x86 为“4”,x64 为“8” ;

更多信息:

https://blog.kenaro.com/2010/12/08/how-to-determine-current-powershell-session-is-x86-or-x64/

因为我们生成的为x64的所以这里判断是否为”8“

同时我们可以看到x86x64的区别。

接下来就是解密一个base64并将其转换为字节数组。

[Byte[]]$var_code = [System.Convert]::FromBase64String('bnlicXZrqsZros8DIy

例如:

$ EncodedText =“VABoAGkAcwAgAGkAcwAgAGEAIABzAGUAYwByAGUAdAAgAGEAbgBkACAAcwBoAG8AdQBsAGQAIABiAGUAIABoAGkAZABlAG4A”
$ DecodedText = [System.Text.Encoding] :: Unicode.GetString([System.Convert] :: FromBase64String($ EncodedText))
$ DecodedText

然后到了一个for语句;

$var_code.Count

-lt :小于

-bxor位异或,两个输入不同时为1,相同时为0(相异为真,否则为假)

例如;我们取$x=1


那么$var_code[$x] -bxor 35

也就是说把所有的数据都bxor然后存放起来。

接下来我们可以看到一个

GetDelegatForFunctionPointer

它允许通过委托实例调用方法,并且GetDelegateForFunctionPointer可以将非托管函数指针转换为委托。

当我们实例化委托时,我们可以将其实例与具有兼容签名和返回类型的任何方法相关联。
那么可以通过委托实例调用(或调用)该方法。

传递给委托方法的第一个参数是对VirtualAlloc的调用:

第二个参数是动态创建的程序集:

然后在下面调用它:

[System.Runtime.InteropServices.Marshal]::Copy:将数据从非托管内存指针复制到托管单精度浮点数数组

使用

GetDelegateForFunctionPointer,VirtualAlloc

传入创建的缓冲区。

然后可以对委托进行实际的调用:

func_get_proc_address

然后我们可以看函数func_get_proc_address部分了

这个函数接受两个参数

$var_module
$var_procedure

列出PowerShell 会话中所有加载的程序集,然后找到在System.dll

中的Microsoft.Win32.UnsafeNativeMethods

([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')

首先获取当前AppDomain中的所有程序集:

[AppDomain]::CurrentDomain.GetAssemblies()

然后通过管道输送到Where-Object获取System.dll

最后调用Microsoft.Win32.UnsafeNativeMethods

在该对象上,GetType用于访问UnsafeNativeMethods.

CS为什么要使用种方法来调用?

Microsoft.Win32.UnsafeNativeMethods is an internal class that cannot be referenced through any direct means.
If you try to reference the class, you will get an error stating  that its module is not loaded. Microsoft.Win32.UnsafeNativeMethods is implemented within System.dll in the GAC. https://twitter.com/mattifestation

此时,Microsoft.Win32.UnsafeNativeMethods已经实现了对类的访问。

接下来就是

$var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))

那么在微软文档中我们知道

GetMethod(String, Type[])

搜索参数与指定参数类型匹配的指定公共方法。

https://docs.microsoft.com/en-us/dotnet/api/system.type.getmethod?view=netcore-3.1#System_Type_GetMethod_System_String_System_Type___

func_get_delegate_type

此函数被调用两次,并接受以下参数:

func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])
func_get_delegate_type @([IntPtr]) ([Void])

第一个参数是方法期望的参数类型,第二个是返回类型。

Param([Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,  
[Parameter(Position = 1)][Type]$var_return_type = [Void])

然后是一个AssemblyBuilder.DefineDynamicAssembly 方法,主要用来定义动态程序集。

DefineDynamicAssembly(AssemblyName,AssemblyBuilderAccess) 
定义具有指定名称和访问权限的动态程序集。
DefineDynamicAssembly(AssemblyName, AssemblyBuilderAccess, IEnumerable<CustomAttributeBuilder>) 
定义具有指定名称、访问权限和属性的新程序集。

在msdn中我们可以看到定义具有指定名称和访问权限的动态程序集的例子

public static System.Reflection.Emit.AssemblyBuilder DefineDynamicAssembly
(System.Reflection.AssemblyName name, System.Reflection.Emit.AssemblyBuilderAccess access);

方便理解我们可以分解为

$1 = [AppDomain]::CurrentDomain.DefineDynamicAssembly($2,$3)
$2 = New-Object System.Reflection.AssemblyName('ReflectedDelegate')$3 = [System.Reflection.Emit.AssemblyBuilderAccess]::Run

然后是定义模块:

.DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
AssemblyBuilder.DefineDynamicModule:在这个程序集中定义一个动态模块。
ModuleBuilder.DefineType:定义类型

往下看就是一个TypeBuilder.DefineConstructor

向动态类型添加一个新的构造函数。

传递给此调用的第一个值是一个逗号分割的属性列表

RTSpecialName:表示公共语言运行时检查名称编码。
HideBySig:表示方法按名称和签名隐藏;否则,仅通过名称。Public:表示该方法可被此对象在其范围内的任何对象访问。

第二个参数是CallingConventions

在本例中设置为Standard

指定由公共语言运行时确定的默认调用约定。将此调用约定用于静态方法。例如或虚拟方法使用HasThis.

接下来是使用SetImplementationFlags设置实现标志。

传递的属性是MethodImplAttributes

这里定义了2个值:

Runtime:指定方法实现由运行时提供
Managed:指定在托管代码中实现该方法。

往下看还是在定义一个方法:

跟上面差不多,主要是用了DefineMethod

https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.typebuilder.definemethod?view=netcore-3.1#System_Reflection_Emit_TypeBuilder_DefineMethod_System_String_System_Reflection_MethodAttributes_System_Reflection_CallingConventions_System_Type_System_Type___System_Type___System_Type___System_Type_____System_Type_____

它向类型添加一个新方法,具有指定的名称、方法属性、调用约定、方法签名和自定义修饰符。

原文由黑白天实验室

生成海报
请发表您的评论
桑云信息Lzers

桑云信息Lzers

乐山桑云信息技术有限公司专注于企业安全与网站、小程序、APP架设,为企业客户提供一站式解决方案,帮助企业快速实现互联网+转型。
909文章数 31评论数
请关注微信公众号
微信二维码
不容错过
Powered By SangYun.Net