#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;