声明
本文所涉及程序均在本地运行测试,用于学习目的,请勿用于非法用途。
前言
利用NetUserAdd添加用户,NetLocalGroupAddMembers添加用户到本地组。
前几天看了一篇文章,调用系统api来添加用户,可以绕过某些防护,于是本地进行实验。
程序分析
程序见文末。 根据文章,添加用户需要使用NetUserAdd。搜索了一下,好心的微软给了一个完整的程序。参加链接1。直接复制下来就可以用。
由于我们是本地使用,不需要域,所以稍作修改。servername参数为NULL时,指向的是本地计算机。所以我们将其默认设置为NULL。就可以完成添加用户的操作。
下一步我们需要添加用户到组,需要使用NetLocalGroupAddMembers函数,继续搜索,发现微软没有给示例代码。/差评。
就需要我们自己来写了。
// add to group
dwLevel = 3;
DWORD totalentries = 1;
LPCWSTR groupname = L"Administrators";
LOCALGROUP_MEMBERS_INFO_3 lmi[1];
lmi[0].lgrmi3_domainandname = argv[1];
nStatus = NetLocalGroupAddMembers(NULL,
groupname,
dwLevel,
(LPBYTE)&lmi,
totalentries);
简单说明一下碰到的问题。
LPCWSTR是wchar_t * ,刚开始直接用char * ,导致找不到组。 后面使用L成功。
有个疑惑的地方是,LOCALGROUP_MEMBERS_INFO_3中的lgrmi3_domainandname是<DomainName>\<AccountName>格式,直接用用户名也可以成功。
buf需要是数组,结果创建了个长度为1的数组,成功运行。
如果编译之后,运行提示缺少dll,可以参考链接3修改。项目 -> 配置属性->C/C++->代码生成->运行库 :选择/MT。
运行
使用管理员权限打开cmd,运行,可以成功。某字会拦截,某容和某家没有提示。
其它
关于lgrmi3_domainandname可以不输入domainname的问题,网上搜索了一下,可以看到链接5的804行,LsapSplitNames函数中对names进行了判断是否存在\,所以存在可以不用输入domainname的情况。
Ptr = wcschr(Names[i].Buffer, L'\\');
if (Ptr == NULL)
{
AccountLength = Names[i].Length / sizeof(WCHAR);
AccountsBuffer[i].Length = Names[i].Length;
AccountsBuffer[i].MaximumLength = AccountsBuffer[i].Length + sizeof(WCHAR);
AccountsBuffer[i].Buffer = MIDL_user_allocate(AccountsBuffer[i].MaximumLength);
源代码
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "netapi32.lib")
#include <stdio.h>
#include <windows.h>
#include <lm.h>
int wmain(int argc, wchar_t* argv[])
{
USER_INFO_1 ui;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;
if (argc != 3)
{
fwprintf(stderr, L"Usage: %s UserName Password \n", argv[0]);
exit(1);
}
//
// Set up the USER_INFO_1 structure.
// USER_PRIV_USER: name identifies a user,
// rather than an administrator or a guest.
// UF_SCRIPT: required
//
ui.usri1_name = argv[1];
ui.usri1_password = argv[2];
ui.usri1_priv = USER_PRIV_USER;
ui.usri1_home_dir = NULL;
ui.usri1_comment = NULL;
ui.usri1_flags = UF_SCRIPT;
ui.usri1_script_path = NULL;
//
// Call the NetUserAdd function, specifying level 1.
//
//nStatus = NetUserAdd(argv[1],
// dwLevel,
// (LPBYTE)&ui,
// &dwError);
nStatus = NetUserAdd(NULL,
dwLevel,
(LPBYTE)&ui,
&dwError);
//
// If the call succeeds, inform the user.
//
if (nStatus == NERR_Success)
fwprintf(stderr, L"User %s has been successfully added on %s\n",
argv[1], L"local");
//
// Otherwise, print the system error.
//
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
// add to group
dwLevel = 3;
DWORD totalentries = 1;
LPCWSTR groupname = L"Administrators";
LOCALGROUP_MEMBERS_INFO_3 lmi[1];
lmi[0].lgrmi3_domainandname = argv[1];
nStatus = NetLocalGroupAddMembers(NULL,
groupname,
dwLevel,
(LPBYTE)&lmi,
totalentries);
//
// If the call succeeds, inform the user.
//
if (nStatus == NERR_Success)
fwprintf(stderr, L"User %s has been successfully added to %s\n",
argv[1], groupname);
//
// Otherwise, print the system error.
//
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
return 0;
}
引用
- https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netuseradd
- https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netlocalgroupaddmembers
- https://blog.csdn.net/Richarll/article/details/6591550
- https://doxygen.reactos.org/d9/df7/local__group_8c.html#ae85c698e825c3f6b9eb711809ad1a03b
- https://doxygen.reactos.org/d9/d99/dll_2win32_2lsasrv_2lookup_8c.html#a91a7fd0133e555e0953cf4f5508cff5b