Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
BridgeHead — 通过 ADWS 以原生 C++ 访问 Active Directory,无需 .NET、无需 WCF、无需 HTTP 协议栈。 | Kitploit
工具/GitHubGitHub/zakipedio/bridgehead
身份验证与授权脚本与自动化信息收集网络安全渗透测试实用工具与框架身份与访问管理 (IAM)红队
GitHubzakipedio/bridgehead

BridgeHead

通过 ADWS 以原生 C++ 访问 Active Directory,无需 .NET、无需 WCF、无需 HTTP 协议栈。

查看仓库
823445个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

BridgeHead

通过 ADWS 原生 C++ 访问 Active Directory,无需 .NET,无需 WCF,无需 HTTP 栈。

BridgeHead 是一个 C++20 静态库,直接在 TCP 之上实现完整的 Active Directory Web Services (ADWS) 协议栈。它得名于 AD 桥头服务器(目录流量流经的网关),为你的 C++ 代码提供与 PowerShell 的 Get-ADUser 和 Get-ADComputer 底层相同的对 9389 端口的低层访问能力。

目录

  • 协议栈
  • 快速开始
  • API 参考
  • 构建
  • 集成
  • 平台支持
  • 依赖项
  • 已知限制
  • 协议参考
  • 许可证

协议栈

传输层通过公共的 bridgehead::transport::IByteStream 接口封装其下的一层。NbfseCodec 是一个编解码工具,由 AdwsClient 调用,用于在成帧之前和之后对 SOAP 消息进行编码/解码:``` AdwsClient WS-Enumeration + WS-Transfer [MS-ADDM] ├── NbfseCodec .NET Binary Format for SOAP [MC-NBFSE] (encode/decode) └── NmfFramer .NET Message Framing [MC-NMF] (send/receive frames) └── NnsSession .NET NegotiateStream [MS-NNS] └── TcpSocket raw TCP/IP

root@kitploit:~
使用者的入口点是 `bridgehead::adws::AdwsClient`。

---

## 快速开始

### 查询并枚举所有用户```cpp
#include "bridgehead/adws/AdwsClient.hpp"

// NTLM (works on any host)
auto client = bridgehead::adws::AdwsClient::EnumerationClient(
    "192.168.1.10",     // DC IP or hostname
    "DC01.corp.local",  // DC FQDN, used in NMF Via header and Kerberos SPN
    "CORP",             // NetBIOS domain name
    "Administrator",    // username
    "Passw0rd"          // password
);

// Kerberos (username hidden on the wire; requires DC reachable on port 88)
auto client = bridgehead::adws::AdwsClient::EnumerationClient(
    "192.168.1.10", "DC01.corp.local", "CORP",
    "Administrator", "Passw0rd",
    bridgehead::adws::AuthPackage::Kerberos
);

auto users = client.Query(
    "(objectClass=user)",
    {"sAMAccountName", "distinguishedName", "memberOf"}
);

for (auto& obj : users)
    std::cout << obj.FirstValue("sAMAccountName") << '\n';

流式传输大型结果集```cpp

client.Enumerate( "(objectClass=computer)", {"dNSHostName", "operatingSystem"}, "", // empty = domain root base DN [](const bridgehead::adws::LdapObject& obj) { std::cout << obj.FirstValue("dNSHostName") << '\n'; return true; // return false to stop early (sends wsen:Release) } );

root@kitploit:~
### 范围与分页```cpp
// OneLevel scope, 50 objects per Pull round-trip
client.Query(
    "(objectClass=user)",
    {"sAMAccountName"},
    "OU=Admins,DC=corp,DC=local",
    50,
    bridgehead::adws::SearchScope::OneLevel
);

二进制属性、objectGUID、objectSid```cpp

auto objs = client.Query("(objectClass=user)", {"objectGUID", "objectSid"}); for (auto& obj : objs) { if (auto* b = obj.FirstBytes("objectGUID")) std::cout << bridgehead::adws::ParseGuid(b) << '\n'; // {XXXXXXXX-...} if (auto b = obj.FirstBytes("objectSid")) std::cout << bridgehead::adws::ParseSid(*b) << '\n'; // S-1-5-... }

root@kitploit:~
### 安全描述符解码```cpp
#include "bridgehead/adws/SecurityDescriptor.hpp"

auto objs = client.Query("(objectClass=user)", {"nTSecurityDescriptor"});
if (auto* raw = objs[0].FirstBytes("nTSecurityDescriptor")) {
    auto sd = bridgehead::adws::ParseSecurityDescriptor(*raw);
    std::cout << "Owner: " << sd.ownerSid << '\n';
    for (auto& ace : sd.dacl.aces)
        std::cout << "  type=" << (int)ace.type
                  << " mask=0x" << std::hex << ace.mask
                  << " sid="   << ace.sid << '\n';
}

写入属性(资源端点)```cpp

auto rc = bridgehead::adws::AdwsClient::ResourceClient( "192.168.1.10", "DC01.corp.local", "CORP", "Administrator", "Passw0rd");

// Modify attributes rc.Put("CN=Alice,OU=Users,DC=corp,DC=local", { {"description", {"managed by bridgehead"}}, {"telephoneNumber", {"555-1234"}}, });

// Clear an attribute (both values and bytes empty = delete) rc.Put("CN=Alice,OU=Users,DC=corp,DC=local", { {"telephoneNumber", {}}, });

// Read back auto obj = rc.Get("CN=Alice,OU=Users,DC=corp,DC=local", {"description", "telephoneNumber"});

// Delete object rc.Delete("CN=TempUser,OU=Users,DC=corp,DC=local");

root@kitploit:~
### LDAP 修改类型:Add / Replace / Delete

`Put` 默认使用 `Replace`(覆盖所有现有值)。如需对多值属性进行精细控制,请使用 `ModifyOperation`:```cpp
using bridgehead::adws::LdapModification;
using bridgehead::adws::ModifyOperation;

rc.Put("CN=Alice,OU=Users,DC=corp,DC=local", {
    // Append a value to an existing multi-valued attribute
    LdapModification{"otherTelephone", {"555-9999"}, {}, ModifyOperation::Add},

    // Remove one specific value (leave others intact)
    LdapModification{"otherTelephone", {"555-0000"}, {}, ModifyOperation::Delete},

    // Replace is the default, explicit here for clarity
    LdapModification{"description", {"updated"}, {}, ModifyOperation::Replace},
});

移动 / 重命名```cpp

// Move to a different OU rc.Move( "CN=Alice,OU=OldOU,DC=corp,DC=local", // current DN "CN=Alice,OU=NewOU,DC=corp,DC=local" // new DN );

// Rename in place (same parent, new CN) rc.Move( "CN=Alice,OU=Users,DC=corp,DC=local", "CN=AliceSmith,OU=Users,DC=corp,DC=local" );

root@kitploit:~
### 写入二进制属性

在 `LdapModification` 的 `bytes` 字段中提供二进制值。它们会在传输线上自动进行 base64 编码:```cpp
std::vector<uint8_t> thumbnail = loadFile("photo.jpg");

rc.Put("CN=Alice,OU=Users,DC=corp,DC=local", {
    LdapModification{"thumbnailPhoto", {}, {thumbnail}},
});

创建对象(ResourceFactory 端点)```cpp

auto rf = bridgehead::adws::AdwsClient::ResourceFactoryClient( "192.168.1.10", "DC01.corp.local", "CORP", "Administrator", "Passw0rd");

rf.Create( "CN=NewUser,OU=Users,DC=corp,DC=local", "user", {{"sAMAccountName", {"newuser"}}, {"userAccountControl", {"512"}}} );

root@kitploit:~
### 异步操作```cpp
#include "bridgehead/adws/AdwsClientAsync.hpp"

auto ac = bridgehead::adws::AdwsClientAsync::EnumerationClient(
    "192.168.1.10", "DC01.corp.local", "CORP", "Administrator", "Passw0rd");

auto future = ac.QueryAsync("(objectClass=user)", {"sAMAccountName"});

// ... do other work while the query runs ...

auto users = future.get();  // blocks until complete; re-throws any exception

慢速 DC 超时:```cpp if (future.wait_for(std::chrono::seconds(5)) == std::future_status::timeout) { // query is still running }

root@kitploit:~
所有操作都有异步变体: `QueryAsync`, `EnumerateAsync`, `GetAsync`, `PutAsync`, `DeleteAsync`, `CreateAsync`, `MoveAsync`。

### 连接池 (高频率 / 多线程工作负载)```cpp
#include "bridgehead/adws/AdwsClientPool.hpp"

// Enumeration pool, Query / Enumerate
bridgehead::adws::AdwsClientPool pool({
    .host = "192.168.1.10", .fqdn = "DC01.corp.local",
    .domain = "CORP", .username = "Administrator", .password = "Passw0rd",
    .maxSize = 4,   // up to 4 concurrent authenticated sessions
});

auto users = pool.Query("(objectClass=user)", {"sAMAccountName"});

// Resource pool, Get / Put / Delete
bridgehead::adws::AdwsClientPool resPool({
    .host = "192.168.1.10", .fqdn = "DC01.corp.local",
    .domain = "CORP", .username = "Administrator", .password = "Passw0rd",
    .maxSize = 4,
    .endpoint = bridgehead::adws::PoolEndpoint::Resource,
});
auto obj = resPool.Get("CN=Alice,OU=Users,DC=corp,DC=local", {"mail"});
resPool.Put("CN=Alice,OU=Users,DC=corp,DC=local", {{"mail", {"[email protected]"}}});

// ResourceFactory pool, Create
bridgehead::adws::AdwsClientPool rfPool({
    .host = "192.168.1.10", .fqdn = "DC01.corp.local",
    .domain = "CORP", .username = "Administrator", .password = "Passw0rd",
    .endpoint = bridgehead::adws::PoolEndpoint::ResourceFactory,
});
rfPool.Create("CN=NewUser,OU=Users,DC=corp,DC=local", "user",
              {{"sAMAccountName", {"newuser"}}});

API 参考

所有公共头文件位于 include/bridgehead/ 下。完整的 API 文档可以通过 Doxygen 生成(参见 构建)。

bridgehead::adws::AdwsClient

bridgehead::adws::AdwsClientAsync

基于 std::future 的异步封装。工厂方法与 AdwsClient 相同;每个操作返回一个 std::future<T>:```cpp std::future<std::vector> f = ac.QueryAsync(...); std::future e = ac.EnumerateAsync(filter, attrs, baseDN, callback); std::future g = ac.GetAsync(...); std::future h = ac.PutAsync(...); std::future i = ac.DeleteAsync(...); std::future j = ac.CreateAsync(...); std::future k = ac.MoveAsync(...);

root@kitploit:~
对于跨多个连接的并发查询,请使用 `AdwsClientPool`。

### `bridgehead::adws::AdwsClientPool`

线程安全的预认证会话池。连接是惰性创建的,并在调用间复用。```cpp
pool.IdleCount();   // sessions currently idle
pool.TotalCount();  // idle + checked-out
pool.MaxSize();     // configured maximum pool size
pool.Move(dn, newDn);  // Move/rename (Resource pool)

`bridgehead::adws::SearchScope````cpp

enum class SearchScope { Base, OneLevel, Subtree /default/ };

root@kitploit:~
### `bridgehead::adws::LdapObject` / `LdapAttribute````cpp
struct LdapAttribute {
    std::string name;
    std::string syntax;                         // LdapSyntax OID, empty if absent
    std::vector<std::string>          values;   // text values (raw base64 for binary)
    std::vector<std::vector<uint8_t>> bytes;    // decoded binary; parallel to values
};

struct LdapObject {
    std::vector<LdapAttribute>  attributes;                          // all returned attributes
    const LdapAttribute*        Find(const std::string& name) const;  // case-insensitive
    std::string                 FirstValue(const std::string& name) const;
    const std::vector<uint8_t>* FirstBytes(const std::string& name) const;
};

二进制辅助工具```cpp

std::string ParseGuid(const std::vector<uint8_t>& bytes); // → "{XXXXXXXX-XXXX-...}" std::string ParseSid (const std::vector<uint8_t>& bytes); // → "S-1-5-..."

root@kitploit:~
### `FilterValue` 与过滤器构建辅助函数

`FilterValue` 是一个类型安全的包装器,在构造时会转义 RFC 4515 §3 元字符(`\`、`*`、`(`、`)`、NUL)。将其与构建辅助函数配合使用,即可从结构上杜绝 LDAP 注入:```cpp
// UNSAFE, raw string concatenation, easy to forget escaping
client.Query("(sAMAccountName=" + username + ")", ...);

// SAFE, FilterValue escapes on construction; FilterEq composes the assertion
FilterValue user = username;
client.Query(FilterEq("sAMAccountName", user), ...);

// Compose complex filters
client.Query(
    FilterAnd({
        FilterEq("objectClass", FilterValue::Raw("user")),  // Raw() for safe literals
        FilterOr({
            FilterEq("sAMAccountName", user),
            FilterEq("mail", FilterValue(email)),
        }),
        FilterNot(FilterPresent("userAccountControl")),
    }), {"sAMAccountName", "mail"}
);

EscapeLdapFilter(str) 仍然可用作底层原语,当您需要手动构建过滤器字符串时。

DnValue 和 DN 构建辅助函数

与 FilterValue 模式相同,但用于可区分名称(DN)的 RDN 值(RFC 4514 §2.4)。转义 ,, +, ", \, <, >, ;, NUL,以及开头/结尾的 # 和空格:```cpp // UNSAFE, comma injection breaks the DN structure rc.Get("CN=" + username + ",OU=Users,DC=corp,DC=local", attrs);

// SAFE DnValue cn = username; // auto-escaped auto dn = BuildDn({DnAttr("CN", cn), "OU=Users", "DC=corp", "DC=local"}); rc.Get(dn, attrs);

// DnValue::Raw() for values you control auto dn2 = BuildDn({DnAttr("CN", DnValue::Raw("Service Account")), "OU=SvcAccounts", "DC=corp", "DC=local"});

root@kitploit:~
### `bridgehead::adws::SecurityDescriptor````cpp
SecurityDescriptor ParseSecurityDescriptor(const std::vector<uint8_t>& bytes);

struct SecurityDescriptor {
    uint16_t    control;       // SdControl::* flags
    std::string ownerSid;
    std::string groupSid;
    bool hasDacl; Acl dacl;
    bool hasSacl; Acl sacl;
};
struct Acl { std::vector<Ace> aces; };
struct Ace {
    uint8_t     type;                  // AceType::*
    uint8_t     flags;                 // AceFlags::*
    uint32_t    mask;
    std::string sid;
    std::string objectType;            // GUID string, object ACEs only
    std::string inheritedObjectType;   // GUID string, object ACEs only
};

常量命名空间:AceType::*、AceFlags::*、SdControl::*。

bridgehead::ConnectionError / AuthenticationError / ProtocolError

定义于 include/bridgehead/Exceptions.hpp(由 AdwsClient.hpp 间接包含)。这三个类均继承自 std::runtime_error:

类型抛出条件
ConnectionErrorTCP 层故障:连接被拒绝、超时、I/O 错误
AuthenticationErrorNTLM/Kerberos 协商失败
ProtocolError任何协议层出现格式错误的服务器响应
try {
root@kitploit:~
auto client = bridgehead::adws::AdwsClient::EnumerationClient(...);
auto users  = client.Query(...);

} catch (const bridgehead::ConnectionError& e) { // unreachable DC, wrong port, timeout } catch (const bridgehead::AuthenticationError& e) { // bad credentials, KDC unreachable } catch (const bridgehead::ProtocolError& e) { // unexpected server response } catch (const bridgehead::adws::SoapFault& e) { // DC returned a SOAP fault (e.g. invalid filter) } // or coarse-grained: // } catch (const std::runtime_error& e) { ... }

root@kitploit:~
### `bridgehead::adws::SoapFault`

当 DC 返回任何 `s:Fault` 响应时抛出,而非普通的 `std::runtime_error`:```cpp
struct SoapFault : std::runtime_error {
    std::string code;     // e.g. "Sender"
    std::string subcode;  // e.g. "InvalidEnumerationContext", empty if absent
    std::string reason;   // human-readable text
};

bridgehead::adws::LdapModification

由 Put 和 Create 使用:```cpp enum class ModifyOperation { Replace /default/, Add, Delete };

struct LdapModification { std::string name; std::vectorstd::string values; // text values std::vector<std::vector<uint8_t>> bytes; // binary values (base64-encoded on the wire) ModifyOperation operation = ModifyOperation::Replace; };

root@kitploit:~
当 `values` 和 `bytes` 均为空时,无论 `operation` 为何,该属性都会被清除/删除。

### `bridgehead::adws::ProtocolLimits`

所有工厂方法、`AdwsClientAsync` 工厂以及 `AdwsClientPool::Config::limits` 的可选最后一个参数。所有字段都有安全的默认值,只有在有特定需求时才建议修改:```cpp
struct ProtocolLimits {
    uint32_t nmfMaxFrameBytes   = 64 * 1024 * 1024;  // max NMF frame (default 64 MiB)
    uint32_t nnsMaxPayloadBytes = 16 * 1024 * 1024;  // max NNS packet (default 16 MB)
    int tcpKeepaliveIdleSec     = 60;   // idle seconds before first probe
    int tcpKeepaliveIntervalSec = 10;   // seconds between probes
    int tcpKeepaliveProbeCount  = 5;    // probes before declaring dead (POSIX only)
};

仅当您读取的对象包含异常大的二进制属性(例如包含许多 ACE 的 nTSecurityDescriptor,或较大的 thumbnailPhoto)时,才提高 nmfMaxFrameBytes / nnsMaxPayloadBytes。在云/NAT 环境中,空闲连接会被主动断开,请调低 keepalive 字段。

命名构造函数辅助函数(内联静态工厂):```cpp LdapModification::Replace(name, values) // Replace with text values (default) LdapModification::ReplaceBinary(name, bytes) // Replace with binary values LdapModification::Append(name, values) // Add to multi-valued attribute LdapModification::Remove(name, values={}) // Remove specific values (or all) LdapModification::Clear(name) // Delete the attribute entirely

root@kitploit:~
---

## 构建

**要求:** CMake 3.25+ 和支持 C++20 的编译器(MSVC 2022+、GCC 12+、Clang 15+)。```bash
# Configure and build (unit tests only, no live AD needed)
cmake -B build -A x64
cmake --build build --config Release

# Run unit tests
ctest --test-dir build -C Release --output-on-failure

# With integration tests (requires a live Domain Controller)
cmake -B build -A x64 -DBRIDGEHEAD_INTEGRATION_TESTS=ON
cmake --build build --config Release
./build/tests/Release/bridgehead_integration_tests.exe

# With CLI tool (adws_list, browse AD objects from the command line)
cmake -B build -A x64 -DBRIDGEHEAD_BUILD_TOOLS=ON
cmake --build build --config Release --target adws_list
./build/tools/Release/adws_list.exe --host <dc-ip> --fqdn <dc-fqdn> --domain <domain> --user <user>

# Generate API reference docs (requires Doxygen)
cmake --build build --target docs
# or directly:
doxygen Doxyfile
# Output: docs/doxygen/html/index.html

CMake 选项


集成

选项 A:CMake 子目录(无需安装)```cmake

add_subdirectory(bridgehead) target_link_libraries(my_target PRIVATE bridgehead::bridgehead)

root@kitploit:~
### 选项 B, 已安装的软件包 (`find_package`)```bash
cmake --install build --prefix /usr/local   # or any install prefix

请提供需要翻译的Markdown内容。```cmake find_package(bridgehead REQUIRED) target_link_libraries(my_target PRIVATE bridgehead::bridgehead)

root@kitploit:~
`pugixml`、`ws2_32` 和 `secur32`(Windows)/ `gssapi_krb5`(Linux/macOS)都会作为传递依赖被引入。

---

## 平台支持

| 平台 | 认证后端 | 状态 |
|----------|-------------|--------|
| Windows | SSPI (`secur32.dll`)、NTLM 和 Kerberos | **可用** |
| Linux / macOS | GSSAPI (`libgssapi_krb5`)、SPNEGO / Kerberos | 已编译;尚未进行集成测试 |

`AuthPackage::Ntlm` 和 `AuthPackage::Kerberos` 在 Windows 上均可使用。Kerberos 在网络上隐藏用户名,是生产环境中的首选;当 KDC(端口 88)不可达时,NTLM 作为回退方案。

在 Linux/macOS 上,GSSAPI 后端使用 SPNEGO 与 Kerberos。如需 NTLM 支持,请安装 `gss-ntlmssp` 插件:```bash
apt install libgss-ntlmssp   # Debian / Ubuntu
dnf install gssntlmssp       # Fedora / RHEL

如果没有该插件,服务器将协商使用 Kerberos。显式的用户/密码凭据使用 gss_acquire_cred_with_password(MIT Kerberos 1.9+);传入空字符串以使用默认凭据缓存(kinit)。GSSAPI 路径可以干净地编译,并且在设计上是正确的,但尚未针对真实 DC 进行端到端验证,请将 Linux/macOS 支持视为测试版。

加密说明: 端口 9389 上的 ADWS 在 NNS 层进行加密(NTLM 会话密钥或 Kerberos AES-256),而非 TLS。这是设计使然,DC 在该端口上不提供 TLS。如果需要基于证书的服务器身份验证,可改用 LDAPS(端口 636)。


依赖项

在配置时通过 cmake/Dependencies.cmake 自动获取,无需手动安装:

库版本用途
Catch2v3.5.2单元测试框架(仅测试目标)
pugixmlv1.14XML DOM(仅用于 ADWS 响应解析)

无 OpenSSL。无 Asio。无 Boost。


已知限制

  • Linux/macOS 上的 NTLM 需要 gss-ntlmssp GSSAPI 插件(参见平台支持)。没有该插件时,服务器将改为协商 Kerberos。Windows 上的 NTLM 通过 SSPI 原生工作。

  • pugixml DOM:每条 SOAP 响应在返回任何结果之前都会被完整解析到内存 XML 树中。这受 maxElements 页面大小(默认每次 Pull 256 个对象)的限制,因此完整结果集不会同时驻留在内存中。仅当页面大小非常大或对象携带较大的二进制属性(例如带有许多 ACE 的对象上的 nTSecurityDescriptor)时,内存才会成为问题。SAX/流式方法可以消除这一问题,但目前尚无计划。


协议参考

  • [MS-ADDM],Active Directory Web Services:数据模型和公共元素
  • [MS-NNS],.NET NegotiateStream 协议
  • [MC-NMF],.NET 消息帧格式
  • [MC-NBFSE],.NET 二进制格式:SOAP 扩展
  • [MS-DTYP],Windows 数据类型(SECURITY_DESCRIPTOR、ACL、ACE、SID、GUID)
  • [MS-ADTS],Active Directory 技术规范(LDAP 筛选器/属性)

所有规范均可从 Microsoft 的开放规范文档 获取。


特别致谢

特别感谢 IBM X-Force 和 SoaPy 项目为本项目提供的灵感、研究以及公开分享的工作。我还要感谢 IBM X-Force Red 的 SoaPy 创建者 Logan Goins,正是他的努力和洞见使这项工作成为可能。


许可证

详情请参阅 LICENSE。

下载工具
方法端点描述
EnumerationClient(host, fqdn, domain, user, pass [, auth, timeoutMs, opTimeoutMs, limits])/Enumeration工厂方法,连接并认证
ResourceClient(...)/Resource用于 Get / Put / Delete / Move 的工厂方法
ResourceFactoryClient(...)/ResourceFactory用于 Create 的工厂方法
Query(filter, attrs [, baseDN, maxElems, scope])Enumeration将所有结果收集到一个 vector 中
Enumerate(filter, attrs, baseDN, callback [, maxElems, scope])Enumeration通过回调流式返回结果
Get(dn, attrs)Resource读取单个对象的属性
Put(dn, modifications)Resource修改属性
Delete(dn)Resource删除对象
Create(dn, objectClass, attrs)ResourceFactory创建新对象
Move(dn, newDn)Resource移动或重命名现有对象
选项默认值描述
BRIDGEHEAD_BUILD_TESTSON构建单元测试套件
BRIDGEHEAD_INTEGRATION_TESTSOFF构建集成测试(需要运行中的 DC)
BRIDGEHEAD_BUILD_TOOLSOFF构建 adws_list CLI 工具