如何通过Delphi中的SYSTEM NT Authority
帐户创建流程?
是否有一个API,如CreateProcessAsUser函数。
答案 0 :(得分:6)
winlogon.exe
进程的标记调用CreateProcessAsUserW。注释
- 如果您希望新进程在同一个调用方会话中运行 WTSQueryUserToken与WtsGetActiveConsoleSessionID获得。CreateEnvironmentBlock 当前活动的用户令牌然后用它调用CreateProcessAsUserW 令牌,并将收到的指针放在{{3}}上。
- 随机设置
醇>Name
&DisplayName
(这样的创造时间) 服务。如果您想使用相同的多个SYSTEM
进程运行 serevice。
我在这里使用
<强> uSysAccount.pas 强>
unit uSysAccount;
interface
uses
WinSvc,
SvcMgr,
Winapi.Windows,
System.SysUtils,
TlHelp32,
System.Classes;
type
TsSysAccount = class(TService)
procedure ServiceExecute(Sender: TService);
private
lpApplicationName,
lpCommandLine,
lpCurrentDirectory: PWideChar;
public
function GetServiceController: TServiceController; override;
end;
procedure CreateProcessAsSystem(const lpApplicationName: PWideChar;
const lpCommandLine:PWideChar = nil;
const lpCurrentDirectory: PWideChar = nil);
var
sSysAccount: TsSysAccount;
implementation
{$R *.dfm}
function WTSQueryUserToken(SessionId: ULONG; var phToken: THandle): BOOL; stdcall; external 'Wtsapi32.dll';
type
TServiceApplicationEx = class(TServiceApplication)
end;
TServiceApplicationHelper = class helper for TServiceApplication
public
procedure ServicesRegister(Install, Silent: Boolean);
end;
function IsUserAnAdmin: BOOL; stdcall; external 'shell32.dll' name 'IsUserAnAdmin';
function CreateEnvironmentBlock(var lpEnvironment: Pointer; hToken: THandle;
bInherit: BOOL): BOOL;
stdcall; external 'Userenv.dll';
function DestroyEnvironmentBlock(pEnvironment: Pointer): BOOL; stdcall; external 'Userenv.dll';
function _GetIntegrityLevel() : DWORD;
type
PTokenMandatoryLabel = ^TTokenMandatoryLabel;
TTokenMandatoryLabel = packed record
Label_ : TSidAndAttributes;
end;
var
hToken : THandle;
cbSize: DWORD;
pTIL : PTokenMandatoryLabel;
dwTokenUserLength: DWORD;
begin
Result := 0;
dwTokenUserLength := MAXCHAR;
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, hToken) then begin
pTIL := Pointer(LocalAlloc(0, dwTokenUserLength));
if pTIL = nil then Exit;
cbSize := SizeOf(TTokenMandatoryLabel);
if GetTokenInformation(hToken, TokenIntegrityLevel,
pTIL, dwTokenUserLength, cbSize) then
if IsValidSid( (pTIL.Label_).Sid ) then
Result := GetSidSubAuthority((pTIL.Label_).Sid, GetSidSubAuthorityCount((pTIL.Label_).Sid )^ - 1)^;
if hToken <> INVALID_HANDLE_VALUE then
CloseHandle(hToken);
LocalFree(Cardinal(pTIL));
end;
end;
function IsUserAnSystem(): Boolean;
const
SECURITY_MANDATORY_SYSTEM_RID = $00004000;
begin
Result := (_GetIntegrityLevel = SECURITY_MANDATORY_SYSTEM_RID);
end;
function StartTheService(Service:TService): Boolean;
var
SCM: SC_HANDLE;
ServiceHandle: SC_HANDLE;
begin
Result:= False;
SCM:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if (SCM <> 0) then
begin
try
ServiceHandle:= OpenService(SCM, PChar(Service.Name), SERVICE_ALL_ACCESS);
if (ServiceHandle <> 0) then
begin
Result := StartService(ServiceHandle, 0, pChar(nil^));
CloseServiceHandle(ServiceHandle);
end;
finally
CloseServiceHandle(SCM);
end;
end;
end;
procedure SetServiceName(Service: TService);
begin
if Assigned(Service) then begin
Service.DisplayName := 'Run as system service created ' + DateTimeToStr(Now);
Service.Name := 'RunAsSystem' + FormatDateTime('ddmmyyyyhhnnss', Now);
end;
end;
procedure CreateProcessAsSystem(const lpApplicationName: PWideChar;
const lpCommandLine:PWideChar = nil;
const lpCurrentDirectory: PWideChar = nil);
begin
if not ( IsUserAnAdmin ) then begin
SetLastError(ERROR_ACCESS_DENIED);
Exit();
end;
if not ( FileExists(lpApplicationName) ) then begin
SetLastError(ERROR_FILE_NOT_FOUND);
Exit();
end;
if ( IsUserAnSystem ) then
begin
SvcMgr.Application.Initialize;
SvcMgr.Application.CreateForm(TsSysAccount, sSysAccount);
sSysAccount.lpApplicationName := lpApplicationName;
sSysAccount.lpCommandLine := lpCommandLine;
sSysAccount.lpCurrentDirectory := lpCurrentDirectory;
SetServiceName(sSysAccount);
SvcMgr.Application.Run;
end
else begin
SvcMgr.Application.Free;
SvcMgr.Application := TServiceApplicationEx.Create(nil);
SvcMgr.Application.Initialize;
SvcMgr.Application.CreateForm(TsSysAccount, sSysAccount);
SetServiceName(sSysAccount);
SvcMgr.Application.ServicesRegister(True, True);
try
StartTheService(sSysAccount);
finally
SvcMgr.Application.ServicesRegister(False, True);
end;
end;
end;
procedure TServiceApplicationHelper.ServicesRegister(Install, Silent: Boolean);
begin
RegisterServices(Install, Silent);
end;
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
sSysAccount.Controller(CtrlCode);
end;
function TsSysAccount.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;
Function ProcessIDFromAppname32( szExeFileName: String ): DWORD;
var
Snapshot: THandle;
ProcessEntry: TProcessEntry32;
Begin
Result := 0;
szExeFileName := UpperCase( szExeFileName );
Snapshot := CreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS,
0 );
If Snapshot <> 0 Then
try
ProcessEntry.dwSize := Sizeof( ProcessEntry );
If Process32First( Snapshot, ProcessEntry ) Then
Repeat
If Pos( szExeFileName,
UpperCase(ExtractFilename(
StrPas(ProcessEntry.szExeFile)))
) > 0
then Begin
Result:= ProcessEntry.th32ProcessID;
Break;
end;
until not Process32Next( Snapshot, ProcessEntry );
finally
CloseHandle( Snapshot );
end;
End;
function TerminateProcessByID(ProcessID: Cardinal): Boolean;
var
hProcess : THandle;
begin
Result := False;
hProcess := OpenProcess(PROCESS_TERMINATE,False,ProcessID);
if hProcess > 0 then
try
Result := Win32Check(TerminateProcess(hProcess,0));
finally
CloseHandle(hProcess);
end;
end;
procedure TsSysAccount.ServiceExecute(Sender: TService);
var
hToken, hUserToken: THandle;
StartupInfo : TStartupInfoW;
ProcessInfo : TProcessInformation;
P : Pointer;
begin
if NOT WTSQueryUserToken(WtsGetActiveConsoleSessionID, hUserToken) then exit;
if not OpenProcessToken(
OpenProcess(PROCESS_ALL_ACCESS, False,
ProcessIDFromAppname32('winlogon.exe'))
,
MAXIMUM_ALLOWED,
hToken) then exit;
if CreateEnvironmentBlock(P, hUserToken, True) then
begin
ZeroMemory(@StartupInfo, sizeof(StartupInfo));
StartupInfo.lpDesktop := ('winsta0\default');
StartupInfo.wShowWindow := SW_SHOWNORMAL;
if CreateProcessAsUserW(
hToken,
lpApplicationName,
lpCommandLine,
nil,
nil,
False,
CREATE_UNICODE_ENVIRONMENT,
P,
lpCurrentDirectory,
StartupInfo,
ProcessInfo) then
begin
end;
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
DestroyEnvironmentBlock(P);
end;
CloseHandle(hToken);
CloseHandle(hUserToken);
TerminateProcessByID(GetCurrentProcessId);
end;
end.
<强> uSysAccount.dfm 强>
object sSysAccount: TsSysAccount
OldCreateOrder = False
DisplayName = 'sSysAccount'
OnExecute = ServiceExecute
Height = 150
Width = 215
end
用法如下(必须以管理员身份运行)
program Project7;
uses
uSysAccount;
{$R *.res}
begin
CreateProcessAsSystem('c:\windows\system32\cmd.exe');
end.