# NetUserAdd逆向

## 起因

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9IV1BIyTYsJrwDQUY%2F-MU9Iv8D4FwsAYblR1Zb%2Fimage.png?alt=media\&token=fcd6c587-1ca0-4f53-810e-ac61ffb6d4ba)

## 过程

反手直接拖ida。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9IV1BIyTYsJrwDQUY%2F-MU9KGDxaWs9fJL500Dc%2Fimage.png?alt=media\&token=fdeec6f4-eb4e-4017-a481-dd87b6343e62)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9IV1BIyTYsJrwDQUY%2F-MU9KWKSKfndke5fhqVB%2Fimage.png?alt=media\&token=6368aba7-93e5-4e33-abfe-758c8a6dd7a9)

跟了下逻辑然后对比了下React OS发现逻辑几乎一致，那直接扣代码。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9IV1BIyTYsJrwDQUY%2F-MU9L6Slg0OQrvfA0dVg%2Fimage.png?alt=media\&token=3f987196-d08c-46aa-872f-d3cc5ed066b5)

win10上UaspOpenDomain没有导出，可以使用特征码搜索的方式去调用，这里跟进了发现同样是调用了sam系函数。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9IV1BIyTYsJrwDQUY%2F-MU9LSYIKF_XhjCiBX30%2Fimage.png?alt=media\&token=2ed8ba1e-ad69-41bb-acaa-0a218b92bb3b)

跟一下函数还需要sid。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9IV1BIyTYsJrwDQUY%2F-MU9M4-oywKHqFh4zigW%2Fimage.png?alt=media\&token=841ef572-9f89-42cc-989f-999780acd5b3)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9IV1BIyTYsJrwDQUY%2F-MU9MAGjGPrxFByt90fJ%2Fimage.png?alt=media\&token=e7f0d4c7-63e4-4888-bd80-15c5c518c0af)

发现是由 LsaQueryInformationPolicy的获取，这个函数在ntsecapi.h里有描述，直接拿来用就好了。

至此用户创建完成，然后通过SetUserInfo设置密码，同样这个函数在windows 10上没有导出。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9MGSQuBYpjsfEHENd%2F-MU9MeyqIOU3yMk3JoUo%2Fimage.png?alt=media\&token=9ca4184a-8d36-460b-a25d-b9ac80de1495)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9MGSQuBYpjsfEHENd%2F-MU9MqPILkHQdprNfYNd%2Fimage.png?alt=media\&token=66c0e3f0-1f0c-44b8-b289-3e22f85495b5)

跟一下，发现下层函数一致并导出。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9MGSQuBYpjsfEHENd%2F-MU9N2teBH84UP6hN7dl%2Fimage.png?alt=media\&token=d3aa9cec-6f9c-4f69-a264-bf3a511376c3)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9MGSQuBYpjsfEHENd%2F-MU9N9D8gfZ60EhPp2Rc%2Fimage.png?alt=media\&token=8ae2d7df-a854-4dca-9bce-d510d95640a9)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9MGSQuBYpjsfEHENd%2F-MU9NEw4oxNTaQhSzC7m%2Fimage.png?alt=media\&token=a2166641-02d5-4b65-b735-01a52ecc6970)

跟踪了一下函数逻辑，发现不同的UserInfo都有不同的处理方法，通常我们会传入一个USERINFO1结构体，这里会把有效信息传入到一个 USER\_ALL\_INFORMATION 结构体里面，这个结构体的实现和Startupinfo有点像，需要同时设置值和使用标签位，阅读发现，有一个结构体单处理密码。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9MGSQuBYpjsfEHENd%2F-MU9OL9sK7eqjtyN3vM5%2Fimage.png?alt=media\&token=bb1c27cb-a68d-45af-9b37-5d48405010b4)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MU9MGSQuBYpjsfEHENd%2F-MU9OTeKHHwEoU2v2gFa%2Fimage.png?alt=media\&token=f96a4884-ec84-4d19-a267-1b17b427d1c3)

这里我们只需要传入密码，然后将标志位设1。

我们就自己封装出了一个NetUserAdd。

## 完整代码

```
#include "ApiAddUser.h"



int wmain(int argc, wchar_t* argv[])
{
	UNICODE_STRING UserName;
	UNICODE_STRING PassWord;
	HANDLE ServerHandle = NULL;
	HANDLE DomainHandle = NULL;
	HANDLE UserHandle = NULL;
	ULONG GrantedAccess;
	ULONG RelativeId;
	NTSTATUS Status = NULL;
	HMODULE hSamlib = NULL;
	HMODULE hNtdll = NULL;
	HMODULE hNetapi32 = NULL;
	LSA_HANDLE hPolicy = NULL;
	LSA_OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
	PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo = NULL;
	USER_ALL_INFORMATION uai = { 0 };


	hSamlib = LoadLibraryA("samlib.dll");
	hNtdll = LoadLibraryA("ntdll");

	pSamConnect SamConnect = (pSamConnect)GetProcAddress(hSamlib, "SamConnect");
	pSamOpenDomain SamOpenDomain = (pSamOpenDomain)GetProcAddress(hSamlib, "SamOpenDomain");
	pSamCreateUser2InDomain SamCreateUser2InDomain = (pSamCreateUser2InDomain)GetProcAddress(hSamlib, "SamCreateUser2InDomain");
	pSamSetInformationUser SamSetInformationUser = (pSamSetInformationUser)GetProcAddress(hSamlib, "SamSetInformationUser");
	pSamQuerySecurityObject SamQuerySecurityObject = (pSamQuerySecurityObject)GetProcAddress(hSamlib, "SamQuerySecurityObject");
	pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");

	RtlInitUnicodeString(&UserName, L"Admin");
	RtlInitUnicodeString(&PassWord, L"Admin");

	Status = SamConnect(NULL, &ServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, NULL);;
	Status = LsaOpenPolicy(NULL,&ObjectAttributes,POLICY_VIEW_LOCAL_INFORMATION,&hPolicy);
	Status = LsaQueryInformationPolicy(hPolicy, PolicyAccountDomainInformation, (PVOID*)&DomainInfo);

	Status = SamOpenDomain(ServerHandle, 
		DOMAIN_CREATE_USER | DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS, 
		DomainInfo->DomainSid, 
		&DomainHandle);

	Status = SamCreateUser2InDomain(DomainHandle,
		&UserName,
		USER_NORMAL_ACCOUNT,
		USER_ALL_ACCESS | DELETE | WRITE_DAC,
		&UserHandle,&GrantedAccess,&RelativeId);

	RtlInitUnicodeString(&uai.NtPassword, PassWord.Buffer);
	uai.NtPasswordPresent = TRUE;
	uai.WhichFields |= USER_ALL_NTPASSWORDPRESENT;


	Status = SamSetInformationUser(UserHandle,
		UserAllInformation,
		&uai);

	return 0;
}
```

## LINKS

{% embed url="<https://doxygen.reactos.org/d2/d5b/dll_2win32_2netapi32_2user_8c.html#a854f5ebc802849632ccda207250e7b04>" %}
