Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
BridgeHead — Native C++ access to Active Directory over ADWS, no .NET, no WCF, no HTTP stack. | Kitploit
Tools/GitHubGitHub/zakipedio/bridgehead
Authentication & AuthorizationScripting & AutomationInformation GatheringNetwork SecurityPenetration TestingUtilities & FrameworksIdentity & Access Management (IAM)Red Teaming
GitHubzakipedio/bridgehead

BridgeHead

Native C++ access to Active Directory over ADWS, no .NET, no WCF, no HTTP stack.

823566 months agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository

BridgeHead

Native C++ access to Active Directory over ADWS, no .NET, no WCF, no HTTP stack.

BridgeHead is a C++20 static library implementing the full Active Directory Web Services (ADWS) protocol stack directly over TCP. Named after the AD bridgehead server, the gateway through which directory traffic flows, it gives your C++ code the same low-level access to port 9389 that PowerShell's Get-ADUser and Get-ADComputer use under the hood.

Table of contents

  • Protocol stack
  • Quick start
  • API reference
  • Build
  • Integration
  • Platform support
  • Dependencies
  • Known limitations
  • Protocol references
  • License

Protocol stack

The transport layers wrap the one below via the common bridgehead::transport::IByteStream interface. NbfseCodec is a codec utility called by AdwsClient to encode/decode SOAP messages before and after framing:

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

The entry point for consumers is bridgehead::adws::AdwsClient.


Quick start

Query, enumerate all users

#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';

Stream large result sets

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)
    }
);

Scope and pagination

// OneLevel scope, 50 objects per Pull round-trip
client.Query(
    "(objectClass=user)",
    {"sAMAccountName"},
    "OU=Admins,DC=corp,DC=local",
    50,
    bridgehead::adws::SearchScope::OneLevel
);

Binary attributes, objectGUID, objectSid

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-...
}

Security descriptor decoding

#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';
}

Write attributes (Resource endpoint)

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");

LDAP modify types, Add / Replace / Delete

Put defaults to Replace (overwrites all existing values). Use ModifyOperation for fine-grained control on multi-valued attributes:

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},
});

Move / Rename

// 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"
);

Write binary attributes

Supply binary values in the bytes field of LdapModification. They are base64-encoded on the wire automatically:

std::vector<uint8_t> thumbnail = loadFile("photo.jpg");

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

Create objects (ResourceFactory endpoint)

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"}}}
);

Async operations

#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

Timeout on a slow DC:

if (future.wait_for(std::chrono::seconds(5)) == std::future_status::timeout) {
    // query is still running
}

All operations have async variants: QueryAsync, EnumerateAsync, GetAsync, PutAsync, DeleteAsync, CreateAsync, MoveAsync.

Connection pool (high-frequency / multi-threaded workloads)

#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]"}}});
Download Tool