![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
CreateProcessAsUser не открисовывает окно запущеного приложения [D6, WinXP]
DelphiN! © (2007-09-27 07:45:00)Запускаю процесс посредством функции CreateProcessAs следующим образом :
function MyCreateProcess(Path,User,Pass: String): Boolean;
const
SE_ASSIGNPRIMARYTOKEN_NAME = 'SeAssignPrimaryTokenPrivilege';
SE_INCREASE_QUOTA_NAME = 'SeIncreaseQuotaPrivilege';
SE_TCB_NAME = 'SeTcbPrivilege';
function EnablePrivilege(lpPrivilegeName: PChar):Boolean;
var
hToken: dword;
NameValue: Int64;
tkp: TOKEN_PRIVILEGES;
ReturnLength: dword;
begin
Result:=false;
OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);
if not LookupPrivilegeValue(nil, lpPrivilegeName, NameValue) then
begin
CloseHandle(hToken);
exit;
end;
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Luid := NameValue;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, false, tkp, SizeOf(TOKEN_PRIVILEGES), tkp, ReturnLength);
if GetLastError() <> ERROR_SUCCESS then
begin
CloseHandle(hToken);
exit;
end;
Result:=true;
CloseHandle(hToken);
end;
var
sti:TStartupInfo;
pi:TProcessInformation;
usertoken:THandle;
st:pointer;
Params,Clean_Path: String;
begin
if not LogonUser(PChar(User),'.',PChar(Pass),LOGON32_LOGON_INTERACTIVE ,LOGON32_PROVIDER_DEFAULT,usertoken) then
begin
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER+FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError,LANG_NEUTRAL,@st,0,0);
ShowMessage(pchar(st));
end;
ZeroMemory(@sti,Sizeof(sti));
EnablePrivilege(SE_INCREASE_QUOTA_NAME);
EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
sti.wShowWindow := 1;
Clean_Path := ExtractPathWithOutParams(Path);
Params := ExtractPathParams(Path);
if not CreateProcessAsUser(usertoken,PChar(Clean_Path),PChar(Params),0,0,false,0,0,0,st i,pi) then
begin
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER+FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError,LANG_NEUTRAL,@st,0,0);
ShowMessage(pchar(st));
end;
end;
MyCreateProcess('C:\WINDOWS\SYSTEM32\CALC.EXE','Admin','pass');
Данный код запускается калькулятор WINDOWS, однако его окно не прорисовано.
Как решить данную проблему?
SLoW.AlfaMoon.Com (2007-10-04 11:32:00) [1]User1999 (04.10.07 01:51) [18]
WinExec(eui.dll_)
Расшифруйте. Хотя, на 99% уверен, что Вы не поняли вопроса или не знакомы с этой областью.
User1999 (2007-10-04 01:51:00) [2]WinExec(eui.dll_)
SLoW.AlfaMoon.Com (2007-10-01 11:02:00) [3]
> Eraser
только с утечкой памяти.
Не спорю. Впрочем, в качестве наброска идеи сойдет.
Eraser (2007-09-28 17:08:00) [4]только с утечкой памяти.
SLoW.AlfaMoon.Com (2007-09-28 16:58:00) [5]Вот эта функция
procedure RunApp(str: pchar);
var
struc1: PSTARTUPINFO;
struc2: PROCESS_INFORMATION;
begin
getmem(struc1, sizeof(TSTARTUPINFO));
struc1^.lpDesktop := PChar('winsta0\default');
struc1^.dwFlags := STARTF_USESHOWWINDOW;
struc1^.wShowWindow := SW_SHOW;
CreateProcess(nil, str, nil, nil, False,
NORMAL_PRIORITY_CLASS,
nil, nil, struc1^, struc2);
end;
Нормально все запускает. Без геморроев.
Eraser (2007-09-28 14:54:00) [6]
> DelphiN! © (28.09.07 14:52) [13]
а что выполняется? неужели сложно отладчиком пройтись или хотя бы простенькое логирование сделать?
DelphiN! (2007-09-28 14:52:00) [7]
> Eraser © (28.09.07 14:41) [12]
Ошибка не формальная, так как ф-ия CreateProcessWithLogonW не выполняется
Eraser (2007-09-28 14:41:00) [8]
> DelphiN! © (28.09.07 13:48) [11]
почти наверняка в какой-то из параметров не правильный параметр передается, инче бы такой ошибки не было. т.е. ошибка по сути формальная скорее всего.
DelphiN! (2007-09-28 13:48:00) [9]
> Eraser © (28.09.07 12:08) [10]
Поправил на
function WTSQueryUserToken(SessionId:ULONG;phToken:pHandle):bool;stdcall;external 'wtsapi32.dll';
WTSQueryUserToken(0, @h);
Результат тот же ...
Где именно Runer.exe выдает ошибку сказать не могу, но видимо при вызове функции CreateProcessWithLogonW, так как другие приложения, не использующие данную функцию ошибки при запуске не выдают ...
Eraser (2007-09-28 12:08:00) [10]
> DelphiN! © (28.09.07 08:47) [9]
> function WTSQueryUserToken(SessionId:pDWord;phToken:pHandle):
> bool;stdcall;external 'wtsapi32.dll';
function WTSQueryUserToken(SessionId: ULONG; var phToken: HANDLE): BOOL; stdcall;
найди 10 отличий, особенно обрати внимение на 1 параметр.
> WTSQueryUserToken(nil, @h);
?
PS
на всякий случай:
где именно
> Runer.exe выдает ошибку
?
DelphiN! (2007-09-28 08:47:00) [11]Нет, к сожалению работает не все.
Использую следующий код для запуска приложений из под LocalSystem аккаунта:
function WTSQueryUserToken(SessionId:pDWord;phToken:pHandle):bool;stdcall;external 'wtsapi32.dll';
procedure StartAsUser(const CmdLine: string);
var
h: THandle;
s: _StartupInfoA;
p: _Process_Information;
begin
WTSQueryUserToken(nil, @h);
s.cb := SizeOf(s);
s.lpReserved:=nil;
s.lpDesktop:=PChar('');
s.lpTitle:=nil;
s.dwFlags:=STARTF_USESHOWWINDOW;
s.wShowWindow:=SW_Show;
s.cbReserved2:=0;
s.lpReserved2:=nil;
CreateProcessAsUser(h, nil, PChar(CmdLine),
nil, nil, false, CREATE_DEFAULT_ERROR_MODE, nil, nil, s, p);
CloseHandle(p.hThread);
CloseHandle(p.hProcess);
CloseHandle(h);
end;
StartAsUser('C:\Runer\Runer.exe RunAs::Admin::pass,Program::C:\WINDOWS\REGEDIT.EXE');
Программа Runer.exe запускается и пытается запустить программу C:\WINDOWS\REGEDIT.EXE через ф-ию CreateProcessWithLogonW под указанным ей в параметрах пользователем, однако при этом Runer.exe выдает ошибку
---------------------------
Runer: Runer.exe - Ошибка приложения
---------------------------
Инструкция по адресу "0x7c913144" обратилась к памяти по адресу "0x00404c55". Память не может быть "written".
"ОК" -- завершение приложения
"Отмена" -- отладка приложения
---------------------------
ОК Отмена
---------------------------
Если выполнить команду C:\Runer\Runer.exe RunAs::Admin::pass,Program::C:\WINDOWS\REGEDIT.EXE из командной строки под тем же пользователем под которым Runer.exe запускается через ф-ию StartAsUser, то программа выполняется без ошибок.
Вот процедура запуска приложения, которую использует Runer.exe
function MyCreateProcess(Path,WorkingDir,User,Pass: String; Alias: String): Boolean;
var
sa: STARTUPINFO;
pi: PROCESS_INFORMATION;
WLogin,WPass,WPath,WFolder: PWideChar;
Folder: String;
lz: Cardinal;
err: array[0..512] of Char;
begin
ZeroMemory(@Sa,Sizeof(sa));
sa.cb := SizeOf(tstartupinfo);
sa.dwFlags := STARTF_USESHOWWINDOW;
sa.wShowWindow := SW_SHOWDEFAULT;
sa.lpReserved := nil;
sa.lpDesktop := nil;
sa.lpTitle := nil;
{New(WLogin); StringToWideChar(WinAccountLogin,WLogin,Length(WinAccountLogin)+1);
New(WPass); StringToWideChar(WinAccountPass,WPass,Length(WinAccountPass)+1);
New(WPath); StringToWideChar(Path,WPath,Length(Path)+1);
Folder := MyExtractFilePath(Path); New(WFolder); StringToWideChar(Folder,WFolder,Length(Folder)+1); }
GetMem(WLogin, Length(User) * SizeOf(WLogin) + 1);
StringToWideChar(User, WLogin, Length(User) * SizeOf(WLogin) + 1);
GetMem(WPass, Length(Pass) * SizeOf(WPass) + 1);
StringToWideChar(Pass, WPass, Length(Pass) * SizeOf(WPass) + 1);
GetMem(WPath, Length(Path) * SizeOf(WPath) + 1);
StringToWideChar(Path, WPath, Length(Path) * SizeOf(WPath) + 1);
Folder := ExtractFilePath(Path);
GetMem(WFolder, Length(Folder) * SizeOf(WFolder) + 1);
StringToWideChar(Folder, WFolder, Length(Folder) * SizeOf(WFolder) + 1);
CreateProcessWithLogonW(WLogin, nil, WPass, 0,
nil, WPath,0, nil, nil, sa, pi);
err := '';
lz := GetLastError;
if lz <> 0 then
begin
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, lz, 0, @err, 512, nil);
MessageBox(0,PChar(String('Error '+IntToStr(lz)+'. '+err)),'',0);
end;
Dispose(WLogin);
Dispose(WPass);
Dispose(WPath);
Dispose(WFolder);
end;
end;
В чем может быть дело?
DelphiN! (2007-09-28 08:21:00) [12]
> Eraser © (27.09.07 12:45) [7]
Громадное спасибо! Все работает!
Eraser (2007-09-27 12:45:00) [13]в зависимости от ОС механизм запуска может сильно меняться, но тем не менее обрати внимание на CreateEnvironmentBlock.
Eraser (2007-09-27 12:43:00) [14]примерно так
stUser: // Текущая терминальная сессия с правами текущего юзера.
begin
if (Win32MajorVersion = 5) and (Win32MinorVersion = 0) then
begin
// 2K: вызов другово способа
Exit;
end
else
begin
// WinXP и выше: используем спец. ф-цию.
if not WTSQueryUserToken(SessionId, hToken) then
begin
dwReturned := GetLastError;
if dwReturned = ERROR_NOT_LOGGED_ON then
Exit;
AppendLog('Error #16 @' + IntToStr(GetLastError));
Exit;
end;
end;
try
if not DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, nil, SecurityIdentification,
TokenPrimary, hNewToken) then
begin
AppendLog('Error #17 @' + IntToStr(GetLastError));
Exit;
end;
if not CreateEnvironmentBlock(lpEnvironment, hNewToken, false) then
begin
AppendLog('Error #18 @' + IntToStr(GetLastError));
Exit;
end;
// Запуск процесса.
si.lpDesktop := 'winsta0\default';
if CreateProcessAsUserW(hNewToken, nil, PWideChar(APath),
nil, nil, false, CREATE_UNICODE_ENVIRONMENT,
lpEnvironment, nil, si, pi) then
begin
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
end
else
begin
AppendLog('Error #19 @' + IntToStr(GetLastError));
Exit;
end;
finally
if hToken <> 0 then
CloseHandle(hToken);
if hNewToken <> 0 then
CloseHandle(hNewToken);
if lpEnvironment <> nil then
DestroyEnvironmentBlock(lpEnvironment);
end;
end;
DelphiN! (2007-09-27 11:57:00) [15]
> clickmaker © (27.09.07 11:51) [4]
Если служба работает под пользователем SYSTEM при попытки запустить процесс под другим пользователем через функцию CreateProcessWithLogonW функция возвращает ошибку 5 - Access Denied
из MSDN :
Windows XP SP2 and Windows Server 2003: You cannot call CreateProcessWithLogonW from a process that is running under the LocalSystem account, because the function uses the logon SID in the caller token, and the token for the LocalSystem account does not contain this SID. As an alternative, use the CreateProcessAsUser and LogonUser functions.
clickmaker (2007-09-27 11:51:00) [16]
> CreateProcessWithLogonW из под службы к сожалению не работает
то есть?
DelphiN! (2007-09-27 10:46:00) [17]
> Игорь Шевченко © (27.09.07 10:08) [2]
Не помогает
Мне необходимо запустить процесс из службы с правами пользовательского аккаунта, служба работает под пользователем SYSTEM.
Данный способ запускает процесс из службы, под пользовательским аккаунтом (смотрел в диспетчере задач), однако у запущенного процесса нет привелегий пользовательского аккаунта, так как он как и служба не может обращаться к сетевым ресурсам(проверял на процессе у которого нет окна).
С этим кодом бьюсь уже неделю, может быть можно как то иначе решить данную проблему? Или что мне нужно сделать с данным кодом чтобы он работал как полагается?
CreateProcessWithLogonW из под службы к сожалению не работает
Нашел пример использования функции CreateProcessAsUser на C, однако к сожалению в С я не силен, а пример достаточно запутанный и громоздкий (
http://win32.mvps.org/security/lu_cpau_gui.cpp
Также есть пример на сайте майкрософта, однако он не меньшего размера и тоже на С.
http://msdn2.microsoft.com/en-us/library/aa379608.aspx
Нашел перевод майкросовтовского примера на Делфи, однако переведено лишь половина кода, далее сообщение обрывается (
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=1899
Больше в интернете примеров на Делфи не нашел (
Игорь Шевченко (2007-09-27 10:08:00) [18]В startupinfo имя desktop-а прописать не поможет ?
Сергей М. (2007-09-27 09:00:00) [19]By default, the new process is non-interactive, that is, it runs on a desktop that is not visible and cannot receive user input.
см. Get/SetProcessWindowStation