Explore the MS-SAMR protocol again

Author: Loong716 @ Amulab

0 x00 preface

In the previous article, “Changing user passwords with MS-SAMR”, I introduced the techniques of changing user passwords with MS-SAMR and restoring them. In this article, we continue to look at some other uses of the MS-SAMR protocol.

0 x01 use

1. Add a local user

During penetration testing, it is not uncommon for an account to be added to the target machine but blocked by the kill software. A common way around this is to add users by calling an API such as NetUserAdd()

We can also add users using SamrCreateUser2InDomain() in the MS-SAMR protocol (which is the underlying implementation of the NetUserAdd() API).

Note the following two points: Domain in Windows (except domain controller)Builtin DomainAccount Domain

  • Builtin domains: Contain the default local groups, such as administrator groups and user groups, that are created when the operating system is installed
  • Account Domain: contains user, group, and local group accounts. The administrator account is in this domain. Accounts defined in the account domain of a workstation or member server are limited to accessing resources that reside on the physical computer where the account resides

So we need to add a normal user in the account domain, then find the Administrators group in the built-in domain, and add the user to Administrators in the built-in domain

The second thing to note is that accounts added with SamrCreateUser2InDomain() are disabled by default, so we need to call SamrSetInformationUser() to clear the disabled flag in the user’s userAccountControl:

// Clear the UF_ACCOUNTDISABLE to enable account
userAllInfo.UserAccountControl &= 0xFFFFFFFE;
userAllInfo.UserAccountControl |= USER_NORMAL_ACCOUNT;
userAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
RtlInitUnicodeString(&userAllInfo.NtOwfPassword, password.Buffer);
​
// Set password and userAccountControl
status = SamSetInformationUser(hUserHandle, UserAllInformation, &userAllInfo);
Copy the code

When implemented, mS-SAMR calls directly can be complex to set up a user password, involving encryption algorithms and possibly requiring an SMB Session Key (impacket works well, but does not support execution as the current user)

However, we can call the samlib.dll export functions. As mentioned in the previous article, these export functions actually encapsulate the protocol call. The implementation is simpler, with the code Demo: github.com/loong716/CP…

2. Resolve password expiration restrictions

Suppose that during penetration testing, we collect a user account for a server, but when we try to access the target SMB resource, we discover that the account password has expired. The psexec landscape is used as an example. The STATUS_PASSWORD_MUST_CHANGE error is displayed:

At this point we can use smbpasswd in Samba to change the user’s password

After changing the password, you can use the new password to access the target SMB resources:

Is actually the smbpasswd call MS – SAMR SamrUnicodeChangePasswordUser2 (), the method does not need context handle, and support the SMB Null Session (Null Session) calls

Github.com/samba-team/…

The example of this method was previously updated by impacket, and the script supports hash passing:

Github.com/SecureAuthC…

3. Collect or modify information

Ms-samr can do many things in information collection/modification, such as enumerating/modifying acLs of objects, user & group information, enumerating password policies, etc. This section uses local administrator group accounts as an example

The NetLocalGroupGetMembers() API is called for enumerating local administrator group accounts. This API also calls the MS-SAMR protocol.

  1. SamrConnect: Gets a handle to the Server object
  2. SamrOpenDomain: Handle to open the target built-in domain
  3. SamrLookupNamesInDomain: Searches for the Administrators RID in the built-in domain
  4. SamrOpenAlias: Opens a unique handle based on the Administrators RID
  5. SamrGetMembersInAlias: Enumerates the member SIDs in the alias object

If we want to develop an automated information gathering tool (such as SharpHound), we need to consider the versatility of the tool. For example, when using SamrLookupNamesInDomain() in step 3, we need to pass in “Administrators”, On some systems, the administrator group name may be different. For example, on some non-English operating systems, the group name may be “Administradors”, or the local administrator group name may be changed by operation maintenance, so it is not appropriate to call NetLocalGroupGetMembers() directly

At this point we can consider optimizing this operation, noting that the RID of the local administrator group is always 544 on different Windows systems

So we can call this:

  1. SamrConnect: Gets a handle to the Server object
  2. SamrOpenDomain: Handle to open the target built-in domain
  3. SamrOpenAlias: Opens a unique handle to the object whose RID is 544
  4. SamrGetMembersInAlias: Enumerates the member SIDs in the alias object

Along these lines, we can leverage the MS-SAMR API for weaponization or optimization of our own tools

4. Add machine accounts in the domain

To add machine accounts to the domain, set AccountType to USER_WORKSTATION_TRUST_ACCOUNT when calling SamCreateUser2InDomain()

// Create computer in domain
status = SamCreateUser2InDomain(hDomainHandle, &computerName, USER_WORKSTATION_TRUST_ACCOUNT, USER_ALL_ACCESS | DELETE | WRITE_DAC, &hUserHandle, &grantAccess, &relativeId);
Copy the code

Addcomputer.py of impacket includes this method because SAMR is added because LDAPS requires certificate instability (SAMR is the protocol used to add machines in the Windows GUI environment)

This seems to be a bit of a mistake, changing unicodePwd over LDAP does require an encrypted connection, but LDAPS is not required, adding machine accounts to encrypted LDAP like Powermad.ps1 can be just as successful and very stable

Most of the time when we add machine accounts in practice, we add machine accounts in order to get an SPN account when we use resource-constrained delegation. However, in my actual test, I found that this method does not automatically add SPN to the machine account, and adding SPN to the machine account through LDAP or other RPC feels a bit superfluous. It can only be used as an implementation method to add machine account, if other methods are not successful

0 x02 reference

Docs.microsoft.com/zh-cn/opens…

Github.com/SecureAuthC…

Snovvcrash. Rocks / 2020/10/31 /…

Blog.cptjesus.com/posts/sharp…