#include <Windows.h>
#include <Aclapi.h>
#pragma comment (lib,"Advapi32.lib")
void SetRegPrivilege()
{
DWORD dwRet;
// 下面这个字符串的值修改为想要进行权限操作的注册表项,注册表每一级的权限是不一样的,所以需要很具体地指定到某一级
LPSTR SamName = "MACHINE\\SAM\\SAM";
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pOldDacl = NULL;
PACL pNewDacl = NULL;
EXPLICIT_ACCESS ea;
HKEY hKey = NULL;
// 获取SAM主键的DACL
dwRet = GetNamedSecurityInfo(SamName, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDacl, NULL, &pSD);
if (dwRet != ERROR_SUCCESS)
{
printf("GetNamedSecurityInfo Error: %d\n", dwRet);
goto FreeAndExit;
}
// 创建一个ACE,允许Everyone完全控制对象,并允许子对象继承此权限
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
BuildExplicitAccessWithName(&ea, "Everyone", KEY_ALL_ACCESS, SET_ACCESS,
SUB_CONTAINERS_AND_OBJECTS_INHERIT);
// 将新的ACE加入DACL
dwRet = SetEntriesInAcl(1, &ea, pOldDacl, &pNewDacl);
if (dwRet != ERROR_SUCCESS)
{
printf("SetEntriesInAcl Error: %d\n", dwRet);
goto FreeAndExit;
}
// 更新SAM主键的DACL
dwRet = SetNamedSecurityInfo(SamName, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDacl, NULL);
if (dwRet != ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo Error: %d\n", dwRet);
goto FreeAndExit;
}
// 打开SAM的子键
dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users\\000001F4",
0, KEY_ALL_ACCESS, &hKey);
if (dwRet != ERROR_SUCCESS)
{
printf("RegOpenKeyEx Error: %d\n", dwRet);
goto FreeAndExit;
}
printf("Open SAM Subkey Successfully.\n");
FreeAndExit:
if (hKey) RegCloseKey(hKey);
if (pNewDacl) LocalFree(pNewDacl);
// 还原SAM主键的DACL
if (pOldDacl) SetNamedSecurityInfo(SamName, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
NULL, NULL, pOldDacl, NULL);
if (pSD) LocalFree(pSD);
return;
}
用delphi实现对NT用户的创建时,首先要查看该NT用户是否已经存在(CheckReg),在检查注册表之前需设置访问权限“完全控制”(SetRegPrivilege),这样就可以用代码操作命令行实现对NT用户的操作(buildaccount)。
Type
NET_API_STATUS = dword;
Type
PLocalGroupUserInfo_0 = ^TLocalGroupUserInfo_0;
TLocalGroupUserInfo_0 = Record
GroupName: LPWSTR;
End;
Function NetUserGetLocalGroups(servername: LPCWSTR; UserName: LPCWSTR;
Level: dword; Flags: dword; Buf: Pointer; PrefMaxLen: dword;
Var EntriesRead: dword; Var TotalEntries: dword): NET_API_STATUS; StdCall;
External 'NETAPI32.DLL ';
Function NetApiBufferFree(Buffer: Pointer): NET_API_STATUS; StdCall;
External 'NETAPI32.DLL ';
function NetUserGetGroups(NetUser: string): boolean;
Const
NERR_Success = 0;
LG_INCLUDE_INDIRECT = 1;
Var
wName: WideString;
dwResult: dword;
P: PLocalGroupUserInfo_0;
PrefMaxLen: dword;
EntriesRead: dword;
TotalEntries: dword;
I: integer;
Buf: Pointer;
begin
wName := NetUser;
PrefMaxLen := $FFFFFFFF;
EntriesRead := 0;
TotalEntries := 0;
Buf := Nil;
dwResult := NetUserGetLocalGroups(Nil, PWideChar(wName), 0,LG_INCLUDE_INDIRECT, @Buf, PrefMaxLen, EntriesRead, TotalEntries);
If dwResult = NERR_Success Then
Begin
If Buf <> Nil Then
Begin
P := PLocalGroupUserInfo_0(Buf);
For I := 0 To EntriesRead - 1 Do
Begin
if P^.GroupName = 'Administrators' then
begin
Result := True;
NetApiBufferFree(Buf);
Exit;
end;
Inc(P);
End;
Result := False;
NetApiBufferFree(Buf);
End;
End;
end;
// winexec是执行外部程序,sw_hide不显示窗体,
// cmd /c是执行完毕后自动关闭。
procedure bulidAccount(UserName, Password: string);
var
CommandLine: string;
sign: boolean;
begin
sign := True;
CommandLine := Format('cmd /c net user %s %s /add', [UserName, Password]);
winexec(PAnsiChar(ansistring(CommandLine)), SW_HIDE);
Sleep(500);
while sign do
begin
CommandLine := Format('cmd /c net localgroup administrators %s /add ', [UserName]);
winexec(PAnsiChar(ansistring(CommandLine)), SW_HIDE);
Sleep(500);
if NetUserGetGroups(UserName) = False then
begin
continue;
end
else
sign := False;
end;
CommandLine := Format('cmd /c net user %s /active:yes', [UserName]);
winexec(PAnsiChar(ansistring(CommandLine)), SW_HIDE);
Sleep(100);
CommandLine := Format('cmd /c net user %s /expires:never', [UserName]);
winexec(PAnsiChar(ansistring(CommandLine)), SW_HIDE);
Sleep(100);
winexec('cmd /c net accounts /maxpwage:unlimited', SW_HIDE);
Sleep(100);
end;
function CheckReg(ntname: string): boolean;
var
RegPath: string;
begin
RegPath := Format('SAM\SAM\Domains\Account\Users\Names\%s', [ntname]);
with TRegistry.Create do
try
RootKey := HKEY_LOCAL_MACHINE;
{ 在读注册项时是在OpenKey('Software',false)时,也就是主键没有打开时可以读;
而在写注册项时是在OpenKey('Software',true)时,也就是在主键打开是才可以写 }
Result := OpenKey(RegPath, false);
finally
Free;
end;
end;
procedure TForm_Reg.SetRegPrivilege; // authority
var
lpObjectName: LPTSTR;
OldDACL, NewDACL: PACL; // uses aclapi
ObjectType: SE_OBJECT_TYPE; // uses AccCtrl
SD: PSECURITY_DESCRIPTOR;
ea: EXPLICIT_ACCESS;
label Cleanup;
begin
lpObjectName := 'MACHINE\SAM\SAM';
ObjectType := SE_REGISTRY_KEY;
// 建立一个空的ACL;
if SetEntriesInAcl(0, nil, nil, OldDACL) <> ERROR_SUCCESS then
exit;
if (SetEntriesInAcl(0, nil, nil, NewDACL) <> ERROR_SUCCESS) then
exit;
// 获取现有的ACL列表到OldDACL
if GetNamedSecurityInfo(lpObjectName, ObjectType, DACL_SECURITY_INFORMATION, nil, nil, OldDACL, nil, SD) <> ERROR_SUCCESS then
Application.MessageBox('指定的键不存在!', '提示', MB_OK);
// 设置用户名"Everyone"对指定的键有所有操作权到结构ea
ZeroMemory(@ea, SizeOf(EXPLICIT_ACCESS));
BuildExplicitAccessWithName(@ea, 'Everyone', // name of trustee
KEY_ALL_ACCESS, // type of access 完全控制 : GENERIC_ALL
SET_ACCESS, // access mode
SUB_CONTAINERS_AND_OBJECTS_INHERIT); // 让自健继承他的权限; inheritance mode
// 合并结构ea和OldDACL的权限列表到新的NewDACL
if SetEntriesInAcl(1, @ea, nil, NewDACL) <> ERROR_SUCCESS then
goto Cleanup;
// 把新的ACL写入到指定的键
SetNamedSecurityInfo(lpObjectName, ObjectType, DACL_SECURITY_INFORMATION, nil, nil, NewDACL, nil);
// 恢复注册表的权限;
BuildExplicitAccessWithName(@ea, 'Everyone', // name of trustee
GENERIC_READ, // type of access
SET_ACCESS, // access mode
NO_INHERITANCE); // 让自健继承他的权限; inheritance mode
if SetEntriesInAcl(1, @ea, nil, OldDACL) <> ERROR_SUCCESS then
goto Cleanup;
// 把旧的ACL写入到指定的键
SetNamedSecurityInfo(lpObjectName, ObjectType, DACL_SECURITY_INFORMATION, nil, nil, OldDACL, nil);
// 释放指针
Cleanup:
if SD <> nil then
LocalFree(HLOCAL(SD));
if NewDACL <> nil then
LocalFree(HLOCAL(NewDACL));
if OldDACL <> nil then
LocalFree(HLOCAL(OldDACL));
end;