1

Тема: AHK: Параметры запущенного приложения

Добрый!
Каким образом можно узнать с какими параметрами было запущено приложение?


http://morik.ucoz.ru/7.jpg

2 (изменено: ilya20069, 2011-11-14 21:47:11)

Re: AHK: Параметры запущенного приложения

Реализация на AutoIt

Реализация на AutoHotKey, но на английском, с которым совсем туго

3

Re: AHK: Параметры запущенного приложения

ProcessName:="svchost.exe"
Query:="Select * from Win32_Process where Name='" . ProcessName . "'"
Gui, Add, ListView, x0 y0 w500 h500, Process Name|Command Line|Pid
For Process In ComObjGet("winmgmts:").ExecQuery(Query)
   LV_Add("", process.Name, Process.CommandLine, process.ProcessId)
Gui, Show,, Process List

4

Re: AHK: Параметры запущенного приложения

http://morik.ucoz.ru/5.jpg

5

Re: AHK: Параметры запущенного приложения

Обнови AHK.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6

Re: AHK: Параметры запущенного приложения

Более конкретный вариант.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7 (изменено: ilya20069, 2011-11-14 22:44:41)

Re: AHK: Параметры запущенного приложения

Спасибо большое. Работает только под _L, в базовой версии нигде не работает.

8

Re: AHK: Параметры запущенного приложения

ilya20069 пишет:

в базовой версии нигде не работает

И не должно!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9 (изменено: Александр_, 2011-11-15 00:33:01)

Re: AHK: Параметры запущенного приложения

он же без перебора процессов:

Process, Exist
pid := ErrorLevel
ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process WHERE ProcessId = " . pid)._NewEnum.next(x)
msgbox % x.CommandLine ;%
ilya20069 пишет:

Спасибо большое. Работает только под _L, в базовой версии нигде не работает.

базовая версия не поддерживает "com". В теме на которую сослался teadrinker я рассказал как действовать в ней, но этот вариант был отсеян из-за сложности.

10

Re: AHK: Параметры запущенного приложения

О, этот вариант гораздо более рационален, благодарю 

11 (изменено: mih, 2011-11-15 02:53:25)

Re: AHK: Параметры запущенного приложения

Александр_, а нельзя ли выудить заодно "current directory" процесса?
Если это "на поверхности", конечно.

Ну и совсем заодно — ещё и pid parent процесса. Эта задача решается тут, но, м.б., есть вариант попроще.

---------
И ещё вопрос. Различные диспетчеры (PE, PH, SE) сканируют процессы "редко", и короткоживущие процессы не оставляют следа в списках. Есть ли какой способ отследить событие запуска процесса, если он достаточно быстро завершается? Это не очень в тему, но если не существует ответа, то не имеет смысла заводить отдельную.

12

Re: AHK: Параметры запущенного приложения

mih пишет:

Александр_, а нельзя ли выудить заодно "current directory" процесса?

Так нельзя, вот список возвращаемых данных. Я бы получал её как и писал в той теме.

mih пишет:

Эта задача решается тут, но, м.б., есть вариант попроще.

Не знаю такого.

mih пишет:

И ещё вопрос. Различные диспетчеры (PE, PH, SE) сканируют процессы "редко", и короткоживущие процессы не оставляют следа в списках. Есть ли какой способ отследить событие запуска процесса, если он достаточно быстро завершается? Это не очень в тему, но если не существует ответа, то не имеет смысла заводить отдельную.

В режиме пользователя это обычно реализуется через перехват функции ZwCreateThread во всех процессах. На AHK это довольно неудобно делать . Если нужно только зарегистрировать сам факт создания процесса, то можно включить аудит процессов в политике аудита windows и читать лог.
Mih, судя по вопросам тебе нужно на "си" переходить .

13

Re: AHK: Параметры запущенного приложения

mih, вопрос не о программном решении задачи — то сие позволяет Process Monitor.

14

Re: AHK: Параметры запущенного приложения

alexii, спасибо, действительно ProcMon показывает такие, я не пользовался им и не знал этого.
Александр_, спасибо тоже за дружеские советы, —

но не до си мне,
не до си, да.

15 (изменено: mih, 2011-11-16 05:16:26)

Re: AHK: Параметры запущенного приложения

Вот штука, сообщающая PID родительского процесса и его имя (при условии, если он ещё существует на момент работы скрипта), взято отсюда:

f11:: 
WinGet, Current_PID, PID, A 
 Parent_PID := GetParentProcessID(Current_PID) 
 Parent_Name:=GetProcessName(Parent_PID) ; имя parent процесса (при условии, если он ещё существует на момент работы скрипта)
 MsgBox Current_PID: %Current_PID%   Parent_PID:  %Parent_PID%  (это - %Parent_Name%)
 Return 


GetParentProcessID(ProcessID) 
{ 
  Return GetProcessInformation(ProcessID, "UInt *", 4, 24)  ; DWORD th32ParentProcessID 
} 

GetProcessName(ProcessID)
{ 
  Return GetProcessInformation(ProcessID, "Str", 260, 36)  ; TCHAR szExeFile[MAX_PATH] 
} 


GetProcessInformation(ProcessID, CallVariableType, VariableCapacity, DataOffset) 
{ 
  hSnapshot := DLLCall("CreateToolhelp32Snapshot", "UInt", 2, "UInt", 0)  ; TH32CS_SNAPPROCESS = 2 
  if (hSnapshot >= 0) 
  { 
    VarSetCapacity(PE32, 304, 0)  ; PROCESSENTRY32 structure -> http://msdn2.microsoft.com/ms684839.aspx 
    DllCall("ntdll.dll\RtlFillMemoryUlong", "UInt", &PE32, "UInt", 4, "UInt", 304)  ; Set dwSize 
    VarSetCapacity(th32ProcessID, 4, 0) 
    if (DllCall("Process32First", "UInt", hSnapshot, "UInt", &PE32))  ; http://msdn2.microsoft.com/ms684834.aspx 
      Loop 
      { 
        DllCall("RtlMoveMemory", "UInt *", th32ProcessID, "UInt", &PE32 + 8, "UInt", 4)  ; http://msdn2.microsoft.com/ms803004.aspx 
        if (ProcessID = th32ProcessID) 
        { 
          VarSetCapacity(th32DataEntry, VariableCapacity, 0) 
          DllCall("RtlMoveMemory", CallVariableType, th32DataEntry, "UInt", &PE32 + DataOffset, "UInt", VariableCapacity) 
          DllCall("CloseHandle", "UInt", hSnapshot)  ; http://msdn2.microsoft.com/ms724211.aspx 
          Return th32DataEntry  ; Process data found 
        } 
        if not DllCall("Process32Next", "UInt", hSnapshot, "UInt", &PE32)  ; http://msdn2.microsoft.com/ms684836.aspx 
          Break 
      } 
    DllCall("CloseHandle", "UInt", hSnapshot) 
  } 
  Return  ; Cannot find process 
}

16

Re: AHK: Параметры запущенного приложения

Александр_ пишет:
mih пишет:

Александр_, а нельзя ли выудить заодно "current directory" процесса?

Я бы получал её как и писал в той теме.

Код для AHK_L, можно переписать и под оригинальный:

;константы
ProcessBasicInformation   := 0
PROCESS_QUERY_INFORMATION := 0x0400
PROCESS_VM_READ           := 0x0010
;функции
;открытие процесса
OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId)
{
   return DllCall("OpenProcess", "uint", dwDesiredAccess, "int", bInheritHandle, "uint", dwProcessId, "uint")
}
;получение информации о процессе
ZwQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength)
{
   return DllCall("ntdll.dll\ZwQueryInformationProcess","uint", ProcessHandle, "uint", ProcessInformationClass, "uint", ProcessInformation, "uint", ProcessInformationLength, "uint", ReturnLength, "uint")
}
;чтение данных из процесса
ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead)
{
   return DllCall("ReadProcessMemory", "uint", hProcess, "uint", lpBaseAddress, "uint", lpBuffer, "uint", nSize, "uint", lpNumberOfBytesRead)
}

Process Exist ;, calc.exe
msgbox % GetProcCurrentDirectory(ErrorLevel) ;%
return 
;получает текущую директорию процесса по его PID'у
GetProcCurrentDirectory(pid)
{
   global ProcessBasicInformation, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ
   hProc := OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, pid)
   if (hProc=0)
   {
      return Error
   }
   VarSetCapacity(ProcessInformation, 0x18) ; под PROCESS_BASIC_INFORMATION
   VarSetCapacity(Buffer, 8)
   VarSetCapacity(ReturnLength, 4) ; формальность
   ZwQueryInformationProcess(hProc, ProcessBasicInformation, &ProcessInformation, 0x18, &ReturnLength)
   ;по смещению 4 располагается адрес PEB
   ReadProcessMemory(hProc, NumGet(&ProcessInformation, 4)+16, &Buffer, 4, &ReturnLength)
   ;по смещению 16 в PEB находится адрес структуры RTL_USER_PROCESS_PARAMETERS
   ReadProcessMemory(hProc, NumGet(&Buffer)+36, &Buffer, 8, &ReturnLength)
   ; слово по смещению 0 содержит длину строки в байтах
   ; двойное слово по смещению 4 содержит адрес строки
   ; строка НЕ заканчивается нулём
   x:=NumGet(&Buffer, 0, "ushort")
   VarSetCapacity(str, x) ; выделяем необходимое место
   ReadProcessMemory(hProc, NumGet(&Buffer, 4), &str, x, &ReturnLength)
   x:=StrGet(&str, x/2, "UTF-16")
   
   VarSetCapacity(ProcessInformation, 0) ; освобождаем память
   VarSetCapacity(str, 0)
   VarSetCapacity(Buffer, 0)
   VarSetCapacity(ReturnLength, 0)
   return x
}

17 (изменено: Александр_, 2011-11-16 00:58:15)

Re: AHK: Параметры запущенного приложения

Александр_ пишет:
mih пишет:

И ещё вопрос. Различные диспетчеры (PE, PH, SE) сканируют процессы "редко", и короткоживущие процессы не оставляют следа в списках. Есть ли какой способ отследить событие запуска процесса, если он достаточно быстро завершается? Это не очень в тему, но если не существует ответа, то не имеет смысла заводить отдельную.

В режиме пользователя это обычно реализуется через перехват функции ZwCreateThread во всех процессах. На AHK это довольно неудобно делать . Если нужно только зарегистрировать сам факт создания процесса, то можно включить аудит процессов в политике аудита windows и читать лог.

Совсем забыл, в WMI ведь тоже есть всякие события/уведомления. Пример, который выводит сообщение при запуске процесса:

WMI := ComObjGet("winmgmts:").ExecNotificationQuery("SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'")
loop
{
    WMIEvent := WMI.NextEvent()
    msgbox % WMIEvent.TargetInstance.ExecutablePath ;%
}
return

Я бы не рекомендовал этим пользоваться, лучше уж самому раз в секунду проверять .

18 (изменено: mih, 2011-11-16 10:13:06)

Re: AHK: Параметры запущенного приложения

Александр_, оба скрипта работают. Рабочую директорию получаю, спасибо.

Но второй — опять же, мониторит только длительноживущие процессы (скрипт с одной стокой "sleep 500" он не замечает, "sleep 1000" — нормально). Поэтому — мою задачу в итоге не решает.

А задача была такая: очень редко (не каждый день) возникает процесс (напр., Блокнот), который запускает неизвестный мне некий "быстроживущий" процесс-родитель (его можно с'имитировать ahk-скриптом с одной строчкой запуска Блокнота) — я хочу этот запускающий процесс "найти и обезвредить". Надо среагировать на возникновение Блокнота (например, твоим скриптом), и сообщить информацию о родительском процессе. PID этого процесса может сообщить скрипт из поста 15, а вот его имя (или ком. строку), если к тому времени процесс уже завершён — добыть не удается. Почему-то система может выдать pid процесса, запустившего Блокнот, но ничего более про него она уже не помнит, — поэтому этот pid бесполезен (я дополнил скрипт в посте 15, теперь он сообщает и имя parent процесса, но при условии, если он существует на момент работы скрипта).
Если таково свойство системы, то такой путь к успеху не приведёт, но можно по-другому: мониторить любой новый процесс и запоминать всё о нём, смотреть, возник ли далее Блокнот, и, — если возник, сообщать всё о предыдущем процессе. Тут и нужен хорошо реагирующий скрипт, но — твой скрипт не видит "быстрых" процессов, и поэтому вроде как бесполезен. А ProcMon (как она прошла мимо меня, удивляюсь, спасибо Alex'у2), похоже, засекает любые "быстрые" процессы, так что возможности какие-то существуют; а может, они что-то в обход системы делают.

?

19

Re: AHK: Параметры запущенного приложения

Александр_ пишет:

Я бы не рекомендовал этим пользоваться, лучше уж самому раз в секунду проверять smile.

Отчего? Утечка памяти была только с объектом Refresher.

20

Re: AHK: Параметры запущенного приложения

mih пишет:

Но второй — опять же, мониторит только длительноживущие процессы (скрипт с одной стокой "sleep 500" он не замечает, "sleep 1000" — нормально). Поэтому — мою задачу в итоге не решает.

Ну в запросе ведь указано проверять раз в секунду, можно и дробное число указать, например пол секунды:
ExecNotificationQuery("SELECT * FROM __InstanceCreationEvent WITHIN 0.5 WHERE TargetInstance ISA 'Win32_Process'")
Кстати, он не только за созданием процессов следит.

mih пишет:

А задача была такая: очень редко (не каждый день) возникает процесс (напр., Блокнот), который запускает неизвестный мне некий "быстроживущий" процесс-родитель (его можно с'имитировать ahk-скриптом с одной строчкой запуска Блокнота) — я хочу этот запускающий процесс "найти и обезвредить". Надо среагировать на возникновение Блокнота (например, твоим скриптом), и сообщить информацию о родительском процессе. PID этого процесса может сообщить скрипт из поста 15, а вот его имя (или ком. строку), если к тому времени процесс уже завершён — добыть не удается. Почему-то система может выдать pid процесса, запустившего Блокнот, но ничего более про него она уже не помнит, — поэтому этот pid бесполезен (я дополнил скрипт в посте 15, теперь он сообщает и имя parent процесса, но при условии, если он существует на момент работы скрипта).
Если таково свойство системы, то такой путь к успеху не приведёт, но можно по-другому: мониторить любой новый процесс и запоминать всё о нём, смотреть, возник ли далее Блокнот, и, — если возник, сообщать всё о предыдущем процессе. Тут и нужен хорошо реагирующий скрипт, но — твой скрипт не видит "быстрых" процессов, и поэтому вроде как бесполезен.

Я выше писал- включи аудит процессов, скрипт вообще не нужен.

mih пишет:

А ProcMon (как она прошла мимо меня, удивляюсь, спасибо Alex'у2), похоже, засекает любые "быстрые" процессы, так что возможности какие-то существуют; а может, они что-то в обход системы делают.

Process Monitor- это утилита от Марка Руссиновича, у него много подобных программ, позволяющих следить за работой ОС Windows, все они рассмотрены в его книгах серии "Windows Internals". Process Monitor устанавливает в систему собственный драйвер, поэтому скриптом его действия повторить нельзя.

alexii пишет:

Отчего? Утечка памяти была только с объектом Refresher.

Может не сработать из-за загруженности процессора. Правда в скриптах другого пути нету.

21 (изменено: mih, 2011-11-16 20:46:02)

Re: AHK: Параметры запущенного приложения

Да, насчет дробного числа - не подумал, но wmiprvse.exe начинает грузить процессор. Аудит посмотрел, вроде работает, но не вижу ком. строки процесса, и вообще всё это в топорном стиле MS: "сложно — о простом". Procmon, кажется, лучше (про утилиты Руссиновича, конечно, знал; но почему-то отложилось: procmon=regmon+filemon). Без скрипта, конечно, обойтись можно; — кстати, за чем он ещё следит?

22

Re: AHK: Параметры запущенного приложения

Александр_ пишет:

Может не сработать из-за загруженности процессора.

У меня такого не случалось.

23

Re: AHK: Параметры запущенного приложения

mih пишет:

Да, насчет дробного числа - не подумал, но wmiprvse.exe начинает грузить процессор.

Ага, именно поэтому лучше самому список процессов проверять.

mih пишет:

за чем он ещё следит?

А хрен его знает. Мне про WMI ничего хорошего не говорили, поэтому я не интересовался подробностями его работы.

alexii пишет:

У меня такого не случалось.

Ну это ведь просто логика! WMI тупо проверяет список каждые N секунд, соответственно если WMI не получит процессорное время, то не сможет вовремя сделать проверку. Вообще тема с запуском процессов уже изъезжена вдоль и поперёк. В режиме пользователя есть только функция CreateProcessNotify, её нужно экспортировать из dll, а саму библиотеку прописать в какой-то параметр реестра. У неё два существенных минуса- библиотека не подгружается в уже работающие процессы и при желании можно создать процесс в обход этого механизма. Все остальные методы базируются на полулегальных перехватах/подменах.

24

Re: AHK: Параметры запущенного приложения

Александр_ пишет:

WMI тупо проверяет список каждые N секунд,

Откуда такая информация?

25 (изменено: mih, 2011-11-17 10:00:10)

Re: AHK: Параметры запущенного приложения

Его логика + моя эмпирика. Процессор грузится, если поставить проверку почаще, с 1ms заметно, — и грузится не скриптом. Прости, что встрял.

26 (изменено: Александр_, 2012-06-01 18:15:44)

Re: AHK: Параметры запущенного приложения

Возвращаясь к WMI и информации о процессах .
WMI почти всю информацию берёт из PEB целевого процесса, таким образом подменив там информацию можно обманывать приложения, использующие эту технологию. А командная строка вообще нигде не сохраняется, кроме как в PEB(по крайней мере я не нашёл). Таким образом, затерев командную строку мы обманем все приложения, которые будут получать её после модификации. Пример кода подменяющего командную строку(проверял только на win7 x64, но должно везде работать):

msgbox % GetCommandLine()
ChangeCommandLine("бугага")
msgbox % GetCommandLine()
return

GetCommandLine()
{
   ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process WHERE ProcessId = " . DllCall("GetCurrentProcessId", "uint"))._NewEnum.next(x)
   return x.CommandLine
}

ChangeCommandLine(NewCommandLine)
{
   VarSetCapacity(ProcessInformation, 6*a_PtrSize, 0)
   VarSetCapacity(ReturnLength, 4, 0)
   x:=DllCall("ntdll.dll\ZwQueryInformationProcess", "ptr", -1, "uint", 0, "ptr", &ProcessInformation, "uint", 6*a_PtrSize, "ptr", &ReturnLength, "int")
   if(x<0)
   {
      msgbox ZwQueryInformationProcess error, return = %x%, GetLastError = %a_lasterror%
      return
   }
   lpPEB := NumGet(&ProcessInformation, A_PtrSize, "ptr")
   if(!lpPEB)
   {
      msgbox не получен адрес PEB
	  return
   }
   lpProcessParameters := NumGet(lpPEB|0, A_PtrSize*4, "ptr")
   if(!lpProcessParameters)
   {
      msgbox не получен адрес RTL_USER_PROCESS_PARAMETERS
	  return
   }
   MaxLen:=NumGet(lpProcessParameters|0, 18+12*A_PtrSize, "ushort")
   CommandLine := NumGet(lpProcessParameters|0, 24+12*A_PtrSize, "ptr")
   if(!CommandLine)
   {
      msgbox не получен адрес командной строки
	  return
   }
   len := strlen(NewCommandLine)*2+2
   if(len>MaxLen)
      len := MaxLen
   NumPut(len-2, 16+12*A_PtrSize, "ushort")
   StrPut(NewCommandLine, CommandLine|0, len/2, "UTF-16")
}

После выполнения функции ChangeCommandLine ни одно приложение не сможет получить командную строку этого скрипта.

27 (изменено: creature.ws, 2012-06-01 16:45:50)

Re: AHK: Параметры запущенного приложения

len всегда будет больше MaxLen, при изменении len := strlen(NewCommandLine)*2 и, в частности, len = 12  — командная строка не изменяется.

28 (изменено: Александр_, 2012-06-01 17:51:59)

Re: AHK: Параметры запущенного приложения

creature.ws пишет:

len всегда будет больше MaxLen, при изменении len := strlen(NewCommandLine)*2 и, в частности, len = 12  — командная строка не изменяется.

Не понял .
MaxLen- это количество байт, выделенное под строку. len- это количество байт нужное для записи строки, не считая нуля на конце(т.е. косяк, нужно было ещё 2 прибавить). Далее если len>MaxLen, то просто записать строку нельзя, потому что может произойти переполнение и нужно либо обрезать строку, либо выделить другой участок памяти и прописать его в lpProcessParameters.
Или ты про опечатку в шестой строке снизу?

29 (изменено: creature.ws, 2012-06-01 17:56:43)

Re: AHK: Параметры запущенного приложения

Или ты про опечатку в шестой строке снизу?

Именно так
С изменением len := strlen(NewCommandLine)*2+2 работает как предполагалось.

30

Re: AHK: Параметры запущенного приложения

creature.ws пишет:

С изменением len := strlen(NewCommandLine)*2+2 работает как предполагалось.

Спасибо, поправил пост.