Форум: "WinAPI";
Текущий архив: 2002.10.17;
Скачать: [xml.tar.bz2];
ВнизПараметры коммандной строки чужего процесса Найти похожие ветки
← →
iptower (2002-08-30 12:47) [0]Как узнать параметры коммандной строки чужего процесса под WIN NT
← →
Игорь Шевченко (2002-08-30 14:05) [1]It"s top secret :-)
www.sysinternals.com - Process Explorer
← →
paul_shmakov (2002-08-30 18:56) [2]а если самостоятельно программно, то вот я набросал пример (сорри, что на C):
//
// rcmdline.cpp
// Get process command line NT/W2K/XP
// Paul Shmakov
//
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
BOOL GetProcessCommandLine(DWORD dwProcessID, LPTSTR szBuffer, DWORD cbBuffer)
{
BOOL bRes = FALSE;
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_READ | PROCESS_VM_OPERATION,
/*PROCESS_ALL_ACCESS,*/ FALSE, dwProcessID);
if(hProcess)
{
#ifndef UNICODE
#define GETCOMMANDLINE "GetCommandLineA"
#else
#define GETCOMMANDLINE "GetCommandLineW"
#endif // UNICODE
LPVOID pGetCommandLine = GetProcAddress(GetModuleHandle(_T("kernel32.dll")),
GETCOMMANDLINE);
if(pGetCommandLine)
{
DWORD dwTID;
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pGetCommandLine, 0, 0, &dwTID);
if(hThread)
{
if(WAIT_OBJECT_0 == WaitForSingleObject(hThread, 10000))
{
LPCSTR pCommandLine = 0;
if(GetExitCodeThread(hThread, (LPDWORD)&pCommandLine))
{
DWORD dwRead;
if(ReadProcessMemory(hProcess, pCommandLine, szBuffer,
cbBuffer, &dwRead))
{
szBuffer[dwRead] = 0;
bRes = TRUE;
}
}
}
CloseHandle(hThread);
}
}
CloseHandle(hProcess);
}
return bRes;
}
BOOL AdjustDebugPriviliges(void)
{
BOOL bRes = FALSE;
HANDLE hTok;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hTok))
{
LUID luid;
TOKEN_PRIVILEGES tp;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bRes = AdjustTokenPrivileges(hTok, FALSE, &tp, NULL, NULL, NULL);
CloseHandle(hTok);
}
return bRes;
}
int _tmain(int argc, char* argv[])
{
if(argc > 1)
{
DWORD dwPID = atoi(argv[1]);
char szCmdLine[1000];
// Needed only to obtain command line of system processes
AdjustDebugPriviliges();
if(GetProcessCommandLine(dwPID, szCmdLine, sizeof(szCmdLine) / sizeof(szCmdLine[0])))
{
printf("Process %d command line: %s\n", dwPID, szCmdLine);
}
else
printf("Failed to obtain command line of process %d\n", dwPID);
}
else
printf("Usage: rcmdline <pid>\n");
return 0;
}
работать будет только под nt/2k/xp, т.к. использует CreateRemoteThread. если нужно решение для всех версий, то без dll дополнительной не обойтись.
пишите dll, которая во время своей инициализации вызывает GetCommandLine и выводит его куда-нибудь или в вызывающий процесс передает.
из своего процесса внедряете эту dll в чужой процесс тем или иным способом.
← →
Ученик (2002-08-30 19:31) [3]Вариант в Delphi
function AdjustDebugPriviliges : Bool;
var
hTok : THandle;
tp : TTokenPrivileges;
begin
Result := False;
if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hTok) then try
if LookupPrivilegeValue(nil, "SeDebugPrivilege", tp.Privileges[0].Luid) then begin
tp.PrivilegeCount := 1;
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
Result := AdjustTokenPrivileges(hTok, False, tp, 0, PTokenPrivileges(nil)^, PDWord(nil)^)
end
finally
CloseHandle(hTok)
end
end;
function GetProcessCommandLine(dwProcessID : DWord; szBuffer : PChar; cbBuffer : DWORD) : Bool;
var
hProcess, hThread : THandle;
pGetCommandLine : Pointer;
pCommandLine : PChar;
dwRead, dwTID : DWord;
begin
Result := FALSE;
hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_READ or PROCESS_VM_OPERATION,
FALSE, dwProcessID);
if (hProcess <> 0) then try
pGetCommandLine := GetProcAddress(GetModuleHandle("kernel32.dll"), "GetCommandLineA");
if (pGetCommandLine <> nil) then begin
hThread := CreateRemoteThread(hProcess, NIL, 0, pGetCommandLine, nil, 0, dwTID);
if (hThread <> 0) then try
if WAIT_OBJECT_0 = WaitForSingleObject(hThread, 10000) then begin
if GetExitCodeThread(hThread, PDWord(@pCommandLine)^) then begin
if ReadProcessMemory(hProcess, pCommandLine, szBuffer, cbBuffer, dwRead) then begin
szBuffer[dwRead] := #0;
Result := TRUE
end
end
end
finally
CloseHandle(hThread)
end
end
finally
CloseHandle(hProcess)
end
end;
procedure TForm1.Button1Click(Sender: TObject);
var
szBuffer : array[0..255] of Char;
begin
AdjustDebugPriviliges;
if GetProcessCommandLine(StrToInt(Edit1.Text), szBuffer, 255) then
ShowMessage(szBuffer)
end;
← →
paul_shmakov (2002-09-01 01:58) [4]2 Ученик:
спасибо за порт :)
← →
Игорь Шевченко (2002-09-02 10:42) [5]В кладовке лежит программа EnumFunctions - там в unit"e main есть функция HSGetWindowCommandLine - несколько другой принцип, не требующий DebugPrivilege. На Delphi :-)
← →
Ученик (2002-09-02 10:48) [6]>Игорь Шевченко © (02.09.02 10:42)
По-моему беда с системными процессами, в этом случае как раз и требуется DebugPrivilege.
← →
Игорь Шевченко (2002-09-02 11:05) [7]Ученик © (02.09.02 10:48)
Мне надо было определить командную строка для окна. Системные процессы окон, вроде, не создают
← →
Ученик (2002-09-02 11:09) [8]>Игорь Шевченко © (02.09.02 11:05)
Имелись ввиду процессы, которые запущены под Local System Account
← →
Игорь Шевченко (2002-09-02 11:10) [9]Ученик © (02.09.02 11:09)
Они тоже, вроде, окон не создают :-)
← →
Ученик (2002-09-02 11:25) [10]>Игорь Шевченко © (02.09.02 11:10)
Сервисы, они ведь разные :-)
← →
Игорь Шевченко (2002-09-02 12:11) [11]Ученик © (02.09.02 11:25)
Вот если у тебя есть пример такого сервиса и тебе не затруднительно проверить мой метод, я был бы очень признателен.
С уважением,
← →
Ученик (2002-09-02 12:28) [12]File-New-Other-Service Application, Interactive=True, и показ какой-нибудь формы на OnStart
← →
Игорь Шевченко (2002-09-02 13:01) [13]Ученик © (02.09.02 12:28)
Увы, не моя область знаний :-(
← →
Ученик (2002-09-02 13:20) [14]>Игорь Шевченко © (02.09.02 13:01)
Значит, не судьба :-)
← →
Игорь Шевченко (2002-09-02 13:27) [15]Ученик © (02.09.02 13:20)
> Значит, не судьба :-)
А тебе очень трудно проверить ? :-)
← →
Ученик (2002-09-02 13:37) [16]>Игорь Шевченко © (02.09.02 13:27)
Да, я проверил, окно в списке не показывается, думал Вы сами хотите, правда окно ToolWindow
← →
Ученик (2002-09-02 13:53) [17]Игорь Шевченко © (02.09.02 13:27)
С обычной формой в сервисе все работает только последняя буква почему то обрезана
← →
Игорь Шевченко (2002-09-02 14:51) [18]Ученик © (02.09.02 13:53)
Спасибо. У меня в списке окон показываются только те, которые появляются на taskbar. Последняя буква - это я спешил и не проверяю, чем строка заканчивается.
Значит, метод не требует DebugPrivilege :-)
P.S. Со мной можно на "ты"
← →
paul_shmakov (2002-09-02 15:28) [19]2 Игорь Шевченко:
в моем примере debug привилегии требуются только для получения командной строки системных процессов, о чем я честно написал:
...
// Needed only to obtain command line of system processes
AdjustDebugPriviliges();
...
← →
Игорь Шевченко (2002-09-02 15:38) [20]paul_shmakov © (02.09.02 15:28)
Если под рукой имеется системный процесс с окном, не очень трудно будет мой способ проверить ? Мне самому интересно :-)
← →
paul_shmakov (2002-09-02 17:28) [21]не нашел я у себя системного процесса с окном. но программа работает. мне вот только интересно:
const
PEBAddress = $7FFDF000;
эта константа на всех операционках равна $7FFDF000?
я достал эту функцию из примера, сунул ее в тестовое консольное приложение. работает! этот способ действительно лучше, т.к. требует меньше привилегий - в OpenProcess требуется только PROCESS_VM_READ, а у меня еще и PROCESS_CREATE_THREAD, PROCESS_VM_OPERATION.
хотя для процесса csrss.exe все равно потребовались debug priviliges.
вот этот тестовый пример (test.dpr):
// (c) Игорь Шевченко
program test;
{$APPTYPE CONSOLE}
uses
Windows, Messages, SysUtils;
type
{ Структура UNICODE_STRING - Передача строковых параметров для Native API и
хранение строк во внутренних структурах Windows }
TUNICODE_STRING = packed record
Length : WORD;
MaximumLength : WORD;
Buffer : PWideChar;
end;
{ Переопределение типов }
UChar = Byte;
Ptr32 = Pointer;
Uint4B = Cardinal;
{ Текущий каталог }
type
TCURDIR = packed record
DosPath : TUNICODE_STRING;
Handle : Ptr32;
end;
{ User Process Parameters - пользовательские параметры процесса }
type
TRTL_USER_PROCESS_PARAMETERS = packed record
MaximumLength : Uint4B;
Length : Uint4B;
Flags : Uint4B;
DebugFlags : Uint4B;
ConsoleHandle : Ptr32;
ConsoleFlags : Uint4B;
StandardInput : Ptr32;
StandardOutput : Ptr32;
StandardError : Ptr32;
CurrentDirectory : TCURDIR;
DllPath : TUNICODE_STRING;
ImagePathName : TUNICODE_STRING;
CommandLine : TUNICODE_STRING;
Environment : Ptr32;
StartingX : Uint4B;
StartingY : Uint4B;
CountX : Uint4B;
CountY : Uint4B;
CountCharsX : Uint4B;
CountCharsY : Uint4B;
FillAttribute : Uint4B;
WindowFlags : Uint4B;
ShowWindowFlags : Uint4B;
WindowTitle : TUNICODE_STRING;
DesktopInfo : TUNICODE_STRING;
ShellInfo : TUNICODE_STRING;
RuntimeData : TUNICODE_STRING;
// +0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR
end;
PRTL_USER_PROCESS_PARAMETERS = ^TRTL_USER_PROCESS_PARAMETERS;
{ Process Environment Block - блок окружения процесса }
type
TPEB = packed record
InheritedAddressSpace : UChar;
ReadImageFileExecOptions : UChar;
BeingDebugged : UChar;
SpareBool : UChar;
Mutant : Ptr32;
ImageBaseAddress : Ptr32;
Ldr : Ptr32; { _PEB_LDR_DATA }
ProcessParameters : PRTL_USER_PROCESS_PARAMETERS { _RTL_USER_PROCESS_PARAMETERS };
SubSystemData : Ptr32;
ProcessHeap : Ptr32;
{ Остальные данные опущены }
end;
PPEB = ^TPEB;
← →
paul_shmakov (2002-09-02 17:29) [22]
function HSGetWindowCommandLine (AProcessID : DWORD) : String;
const
PEBAddress = $7FFDF000;
var
AProcessHandle : THandle;
ATargetProcessParametersPointer : Ptr32;
ATargetProcessParameters : TRTL_USER_PROCESS_PARAMETERS;
ATargetCommandLine : array[0..MAX_PATH] of WideChar;
AReturned : DWORD;
APathBytes : WORD;
begin
Result := "";
{ Алгоритм пригоден только для NT-платформ }
if true {HSQuerySystemInfo(hsiNTPlatform)} then begin
{ handle этого процесса }
AProcessHandle := OpenProcess(PROCESS_VM_READ, false, AProcessID);
if AProcessHandle = 0 then
RaiseLastWin32Error();
try
{ Получение адреса структуры параметров процесса }
if NOT ReadProcessMemory(AProcessHandle,
{ Этот оператор нужен для подсчета смещения в блоке
PEB на указатель на параметры процесса }
@PPEB(PEBAddress)^.ProcessParameters,
@ATargetProcessParametersPointer, SizeOf(Ptr32),
AReturned) then
RaiseLastWin32Error();
{ Проверка избыточна, но вставлена для пущей надежности. }
if AReturned <> SizeOf(Pointer) then
raise Exception.CreateFmt(
"ReadProcessMemory прочитала неверное количество данных, ожидалось %d, получено %d",
[SizeOf(Ptr32), AReturned]);
{ Получение структуры параметров процесса }
if NOT ReadProcessMemory(AProcessHandle, ATargetProcessParametersPointer,
@ATargetProcessParameters,
SizeOf(ATargetProcessParameters),
AReturned) then
RaiseLastWin32Error();
{ Проверка избыточна, но вставлена для пущей надежности. }
if AReturned <> SizeOf(ATargetProcessParameters) then
raise Exception.CreateFmt(
"ReadProcessMemory прочитала неверное количество данных, ожидалось %d, получено %d",
[SizeOf(ATargetProcessParameters), AReturned]);
{ размер командной строки в байтах }
APathBytes := ATargetProcessParameters.CommandLine.Length;
if APathBytes > MAX_PATH * SizeOf(WideChar) then
APathBytes := MAX_PATH * SizeOf(WideChar);
{ Получение командной строки для указанного процесса }
if NOT ReadProcessMemory(AProcessHandle,
ATargetProcessParameters.CommandLine.Buffer,
@ATargetCommandLine,
APathBytes,
AReturned) then
RaiseLastWin32Error();
{ Для преобразования в Ansi подсчитывается число символов Unicode без
завершающего нуля. lstrlenW почему-то дала неверный результат. Странно.}
Result := WideCharLenToString(ATargetCommandLine,
Pred(AReturned DIV SizeOf(WideChar)));
finally
CloseHandle(AProcessHandle);
end;
end;
end;
function SetDebugPriv: Boolean;
var
Token: THandle;
tkp: TTokenPrivileges;
begin
Result := false;
if OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then
begin
if LookupPrivilegeValue(nil, PChar("SeDebugPrivilege"), tkp.Privileges[0].Luid) then
begin
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
Result := AdjustTokenPrivileges(Token, false, tkp, 0, PTokenPrivileges(nil)^, PDWord(nil)^);
end;
end;
end;
var
ProcessID: DWORD;
begin
// Убирите комментарий для процесса crcss.exe
// SetDebugPriv;
// Введите id процесса
ProcessID := ????;
WriteLn(HSGetWindowCommandLine(ProcessID));
end.
← →
Игорь Шевченко (2002-09-02 18:11) [23]paul_shmakov © (02.09.02 17:29)
Большое спасибо!
> const
> PEBAddress = $7FFDF000;
>
> эта константа на всех операционках равна $7FFDF000?
Да. Программа проверялась на WinNT 4.0 (SP6), Win2000 и WinXP
По-хорошему для будущих версий можно использовать функцию
RtlGetCurrentPeb, но я не знаю, на всех ли она NT-платформах поддерживается. В NTDLL.DLL от WinXP - есть.
Кстати, купил книжку Гари Неббета по Native API в Библио-глобусе :-)
С уважением,
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2002.10.17;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.008 c