API修改访问注册表的权限

#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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章