前言
这里分析的为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“
;
同时我们可以看到x86
和x64
的区别。
接下来就是解密一个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
设置实现标志。
传递的属性是MethodImplAttribute
s
:
这里定义了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_____
它向类型添加一个新方法,具有指定的名称、方法属性、调用约定、方法签名和自定义修饰符。
本文始发于微信公众号(黑白天实验室):CS Powershell Beacon分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论