Ладно, эта статья не будет переполнена теорией. Я думаю, что использование
toolhelp'а достаточно легко, поэтому я объясню функции API, которые относятся
к нему без всякой теоретической чепухи.
Итак, если у нас есть доступ к функциям Toolhelp (не в NT4), вы можете узнать
о процессах, модулях, тредах и кучах, которые запущены сейчас в системе.
Прекрасно... теперь немного теории :))). Есть нечто, что называется снапшотом
системы. MSDN говорит: "Снапшот - это доступная только для чтения копия
текущего состояния одного или более из следующих списков объектов,
находящихся в системе: процессы, треды, модули и кучи." И это правда :))).
Поэтому, если вы можете получить хэндл снапшота, вы можете увидеть запущенные
в системе процессы и получить их полные пути. Отлично... с теорией все :))).
Чтобы получить хэндл снапшота, используйте функцию CreateToolhelp32Snapshot:
Функция возвращает хэндл текущего снапшота
-1, если вызов не удался - используйте GetLastError
для получения расширенной
информации
флаги - TH32CS_SNAPHEAPLIST = 1 ; включить список куч в снапшот
TH32CS_SNAPPROCESS = 2 ; включить списко процессов
TH32CS_SNAPTHREAD = 4 ; включить список тредов
TH32CS_SNAPMODULE = 8 ; включить список модулей
TH32CS_SNAPALL = 1 | 2 | 4 | 8 ; в снапшот будет включено все
TH32CS_INHERIT = 080000000h ; снапшот может наследоваться
Теперь у нас есть хэндл снапшота, который нам требовался. После того, как
мы закончим с ним работать, его можно закрыть с помощью функции CloseHandle.
push хэндл снапшота
call CloseHandle
Представьте, что у нас есть хэндл снапшота процессов...
Обход процессов (и всего остального, что включено в снапшот) похож на обход
файлов с помощью FindFirstFile и FindNextFile.
push указатель на структуру PROCESSENTRY32
push хэндл снапшота
call Process32First
Функция возращает TRUE в случае успеха, переданная структура содержит
данные
PROCESSENTRY32 struc
_size dd ? ; размер структур - нужно установить до вызова
_usage dd ? ; ссылок на процесс - живет, пока не равно нулю
_processID dd ? ; PID
_defaultHeapID dd ? ; ID кучи процесса по умолчанию
_moduleID dd ? ; MID :))
_threads dd ? ; количество запущенных процессом тредов
_parentProcessID dd ? ; PID процесса, создавшего наш процесс
_priClassBase dd ? ; базовый приоритет тредов
_flags dd ? ; зарезервировано
_exeFile db 255 dup(?) ; лучшее напоследок - полный путь к процессам!
PROCESSENTRY32 ends
Чтобы получить следующий процесс:
|
push указатель на структуру PROCESSENTRY32
push хэндл снапшота
call Process32Next
Функция возвращает TRUE в случае успеха, PROCESSENTRY32 содержит данные
Есть еще одна функция, предоставленная Toolhelp, для работы с процессами:
push сколько байтов считать в буфер ; если NULL - игнорируется
push сколько байтов считать из процесса
push указатель на буфер
push адрес для чтения
push PID ; PID процесса, из которого будет произведено чтение
call Toolhelp32ReadProcessMemory
Функция возвращает TRUE в случае успеха
адрес для чтения - это значение сначала проверяется системой, поэтому если
у вас нет доступа, функция не сработает.
Представьте, что у нас есть хэндл снапшота модулей...
Этот снапшот включает список модулей, используемых каждым запущенным
процессов.
push указатель на структуру MODULEENTRY32
push хэндл снапшота
call Module32First
push указатель на структуру MODULEENTRY32
push хэндл снапшота
call Module32Next
MODULEENTRY32 struc
_size dd ? ; размер структуры - должен быть установлен до вызова
_moduleID dd ? ; MID - в контексте процесса-владельца
_processID dd ? ; PID проверяющего процесса
_glblcntUsage dd ? ; глобальных ссылок на модуль
_proccntUsage dd ? ; ссылок процесса на модуль
_modBaseAddr dd ? ; базовый адрес модуля в контексте процесса
_modBaseSize dd ? ; размер модуля
_hModule dd ? ; хэндл модуля в контексте процесса
_module db 255 + 1 dup(?) ; имя модуля
_exePath db 255 dup(?) ; путь к модулю
MODULEENTRY32 ends
Представьте, что у нас есть хэндл снапшота куч
С помощью этого снапшот мы можем узнать о куче каждого из запущенных
процессов. сначала мы должны получить ID кучи в процессе. Это делается так:
push HEAPLIST32
push хэндл снапшота
call Heap32ListFirst
push HEAPLIST32
push хэндл снапшота
call Heap32ListNext
HEAPLIST32 struc
_size dd ? ; уфффф... это размер...
_processID dd ? ; PID процесса-владельца
_teapID dd ? ; идентификатов кучи
_flags dd ? ; определено как HF32_DEFAULT = 1
HEAPLIST32 ends
Ладно, с помощью этой функции мы получаем ID кучи, который понадобиться нам
в дальнейшем:
push heapID ; идентификатор кучи, который возвращается функциями xListX
push PID ; PID процесса-владельца
push HEAPENTRY32
call Heap32First
push HEAPENTRY32
call Heap32Next
HEAPENTRY32 struc
_size dd ? ; вы уже поняли :)
_handle dd ? ; хэндл блока кучи
_address dd ? ; линейный адрес начала блока
_blockSize dd ? ; размер блока кучи
_flags dd ? ; смоти ниже
_lockCount dd ? ; количество закрытий (Global[Local]Lokh)
_resvd dd ? ; зарезервировано
_processID dd ? ; PID проверяемого процесса
_heapID dd ? ; ID кучи в контексте процесса
HEAPENTRY32 ends
_flags - LF32_FIXED = 1 ; блок памяти имеет фиксированное местоположение
LF32_FREE = 2 ; блок памяти свободен
LF32_MOVEABLE = 4 ; блок памяти можно переместить
Представьте, что у нас есть хэндл снапшота тредов
push указатель на структуру THREADENTRY32
push хэндл снапшота
call Thread32First
и
push указатель на структуру THREADENTRY32
push хэндл снапшота
call Thread32Next
Функция возвращает то же, что и аналогичные функции работы с процессами
THREADENTRY32 struc
_size dd ? ; размер структуры
_usage dd ? ; ссылок на тред - живет, пока не равно нулю
_threadID dd ? ; идентификатор треда
_ownerProcessID dd ? ; PID процесса, которые владеет тредом
_basePri dd ? ; начальный уровень приоритета
_deltaPri dd ? ; разность со знаком относительно базового приоритета
_flags dd ? ; зарезервировано
THREADENTRY32 ends
Напоследок
Ладно, это все, что я нашел о Toolhelp.