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