前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CS Powershell Beacon分析

CS Powershell Beacon分析

作者头像
黑白天安全
发布2021-09-07 11:21:02
1.8K1
发布2021-09-07 11:21:02
举报

前言

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

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

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

第一部分

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

代码语言:javascript
复制
[IntPtr]::size -eq 8

这里返回一个True

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

代码语言:javascript
复制
x86 为“4”,x64 为“8” ;

更多信息:

代码语言:javascript
复制
https://blog.kenaro.com/2010/12/08/how-to-determine-current-powershell-session-is-x86-or-x64/

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

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

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

代码语言:javascript
复制
[Byte[]]$var_code = [System.Convert]::FromBase64String('bnlicXZrqsZros8DIy

例如:

代码语言:javascript
复制
$ 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然后存放起来。

接下来我们可以看到一个

代码语言:javascript
复制
GetDelegatForFunctionPointer

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

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

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

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

然后在下面调用它:

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

使用

代码语言:javascript
复制
GetDelegateForFunctionPointer,VirtualAlloc

传入创建的缓冲区。

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

func_get_proc_address

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

这个函数接受两个参数

代码语言:javascript
复制
$var_module
$var_procedure

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

中的Microsoft.Win32.UnsafeNativeMethods

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

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

代码语言:javascript
复制
[AppDomain]::CurrentDomain.GetAssemblies()

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

最后调用Microsoft.Win32.UnsafeNativeMethods

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

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

代码语言:javascript
复制
Microsoft.Win32.UnsafeNativeMethods is an internal class that cannot be referenced through any direct means.
代码语言:javascript
复制
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已经实现了对类的访问。

接下来就是

代码语言:javascript
复制
$var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))

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

代码语言:javascript
复制
GetMethod(String, Type[])

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

代码语言:javascript
复制
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

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

代码语言:javascript
复制
func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])
func_get_delegate_type @([IntPtr]) ([Void])

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

代码语言:javascript
复制
Param([Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,  
[Parameter(Position = 1)][Type]$var_return_type = [Void])

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

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

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

代码语言:javascript
复制
public static System.Reflection.Emit.AssemblyBuilder DefineDynamicAssembly
(System.Reflection.AssemblyName name, System.Reflection.Emit.AssemblyBuilderAccess access);

方便理解我们可以分解为

代码语言:javascript
复制
$1 = [AppDomain]::CurrentDomain.DefineDynamicAssembly($2,$3)
$2 = New-Object System.Reflection.AssemblyName('ReflectedDelegate')$3 = [System.Reflection.Emit.AssemblyBuilderAccess]::Run

然后是定义模块:

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

往下看就是一个TypeBuilder.DefineConstructor

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

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

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

第二个参数是CallingConventions

在本例中设置为Standard

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

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

传递的属性是MethodImplAttributes

这里定义了2个值:

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

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

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

代码语言:javascript
复制
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_____

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 黑白天实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 第一部分
  • func_get_proc_address
  • func_get_delegate_type
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档