Работа с сервисами Windows на Ассемблере
Работа с сервисами Windows на Ассемблере
Давно хотел поэкспериментировать с сервисами Windows, наконец дошли руки. Еще со времен Windows XP я пользуюсь программой Service Tree от А.Н.Гусарова, но в ней имеются досадные косяки, поэтому есть большое желание написать что-нибудь подобное. А в этой статье будут складироваться все наработки по теме сервисов.
Начинаем с описания констант и структур, которых нет в FASM, но которые нам будут нужны для дальнейшей работы с сервисами.
Code (Assembler) : Убрать нумерацию
- SC_MANAGER_ALL_ACCESS = 0xF003F
- SERVICE_ALL_ACCESS = 0xF01FF
- SERVICE_QUERY_CONFIG = 0x0001
- SERVICE_QUERY_STATUS = 0x0004
- SERVICE_CHANGE_CONFIG = 0x0002
- SERVICE_ENUMERATE_DEPENDENTS = 0x0008
- SERVICE_START = 0x0010
- SERVICE_STOP = 0x0020
- DELETE = 0x10000
- SERVICE_NO_CHANGE = 0xFFFFFFFF
- SERVICE_CONTROL_STOP = 0x00000001
- SERVICE_WIN32_OWN_PROCESS = 0x00000010
- SERVICE_WIN32_SHARE_PROCESS = 0x00000020
- SERVICE_ACTIVE = 0x00000001
- SERVICE_INACTIVE = 0x00000002
- SERVICE_STATE_ALL = 0x00000003
- SERVICE_STOPPED = 0x00000001
- SERVICE_START_PENDING = 0x00000002
- SERVICE_STOP_PENDING = 0x00000003
- SERVICE_RUNNING = 0x00000004
- SERVICE_CONTINUE_PENDING = 0x00000005
- SERVICE_PAUSE_PENDING = 0x00000006
- SERVICE_PAUSED = 0x00000007
- SERVICE_BOOT_START = 0x00000000
- SERVICE_SYSTEM_START = 0x00000001
- SERVICE_AUTO_START = 0x00000002
- SERVICE_DEMAND_START = 0x00000003
- SERVICE_DISABLED = 0x00000004
- struct SERVICE_STATUS
- dwServiceType dd ?
- dwCurrentState dd ?
- dwControlsAccepted dd ?
- dwWin32ExitCode dd ?
- dwServiceSpecificExitCode dd ?
- dwCheckPoint dd ?
- dwWaitHint dd ?
- ends
- struct ENUM_SERVICE_STATUS
- lpServiceName dd ?
- lpDisplayName dd ?
- ServiceStatus SERVICE_STATUS
- ends
- struct QUERY_SERVICE_CONFIG
- dwServiceType dd ?
- dwStartType dd ?
- dwErrorControl dd ?
- lpBinaryPathName dd ?
- lpLoadOrderGroup dd ?
- dwTagId dd ?
- lpDependencies dd ?
- lpServiceStartName dd ?
- lpDisplayName dd ?
- ends
- struct QUERY_SERVICE_LOCK_STATUS
- fIsLocked dd ?
- lpLockOwner dd ?
- dwLockDuration dd ?
- ends
Code (Assembler) : Убрать нумерацию
- ; Открыть менеджер сервисов
- invoke OpenSCManager,NULL,NULL,SC_MANAGER_ALL_ACCESS
- or eax,eax
- jz loc_exit
- mov [scm],eax
- ; ResumeHandle перед вызовом должен быть обнулен
- mov [ResumeHandle],0
- ; Определить необходимый размер памяти
- invoke EnumServicesStatus,[scm],\
- SERVICE_WIN32_OWN_PROCESS+SERVICE_WIN32_SHARE_PROCESS,\
- SERVICE_ACTIVE+SERVICE_INACTIVE,tmp,0,\
- BytesNeeded,ServicesReturned,ResumeHandle
- ; Выделить память
- invoke GlobalAlloc,GMEM_FIXED+GMEM_ZEROINIT,[BytesNeeded]
- mov [mem],eax
- invoke GlobalLock,eax
- mov [Services],eax
- ; ResumeHandle перед вызовом должен быть обнулен
- mov [ResumeHandle],0
- ; Получить список сервисов
- invoke EnumServicesStatus,[scm],\
- SERVICE_WIN32_OWN_PROCESS+SERVICE_WIN32_SHARE_PROCESS,\
- SERVICE_ACTIVE+SERVICE_INACTIVE,[Services],[BytesNeeded],\
- BytesNeeded,ServicesReturned,ResumeHandle
- ; Получить данные каждого сервиса
- mov ebx,[Services]
- loc_enum_services:
- ; Открыть сервис
- invoke OpenService,[scm],[ebx+ENUM_SERVICE_STATUS.lpServiceName],\
- SERVICE_QUERY_CONFIG
- or eax,eax
- jz loc_next_service
- mov [hService],eax
- ; Определить необходимый размер памяти
- invoke QueryServiceConfig,[hService],qsc,0,BytesNeeded
- ; Выделить память
- invoke GlobalAlloc,GMEM_FIXED+GMEM_ZEROINIT,[BytesNeeded]
- mov [mem2],eax
- invoke GlobalLock,eax
- mov [Service],eax
- ; Получить данные сервиса
- invoke QueryServiceConfig,[hService],[Service],[BytesNeeded],BytesNeeded
- mov ecx,[Service]
- ; ECX -> указатель на структуру QUERY_SERVICE_CONFIG
- ; EBX -> указатель на структуру ENUM_SERVICE_STATUS
- ...
- ; Какие-то действия с сервисом
- ...
- ; Освободить память
- invoke GlobalUnlock,[Service]
- invoke GlobalFree,[mem2]
- ; Закрыть сервис
- invoke CloseServiceHandle,[hService]
- loc_next_service:
- ; Следующий сервис
- add ebx,sizeof.ENUM_SERVICE_STATUS
- ; Все сервисы отработали?
- dec [ServicesReturned]
- cmp [ServicesReturned],0
- ja loc_enum_services
- ; Освободить память
- invoke GlobalUnlock,[Services]
- invoke GlobalFree,[mem]
- ; Закрыть менеджер сервисов
- invoke CloseServiceHandle,[scm]
Отдельно хочу остановиться на зависимых сервисах, то есть прочих сервисах, от которых зависит работоспособность выбранного сервиса или наоборот, работоспособность которых зависит от выбранного сервиса. При получении конфигурации сервиса в поле lpDependencies структуры QUERY_SERVICE_CONFIG содержится указатель на список имен сервисов, от которых зависит работоспособность выбранного сервиса. Список хранится в виде строк, разделенных нулевым символом и заканчивается двойным нулевым символом. Для получения названия сервисов можно воспользоваться функцией GetServiceDisplayName.
Code (Assembler) : Убрать нумерацию
- ; EBX -> указатель на структуру QUERY_SERVICE_CONFIG
- ; Первый сервис, от которого зависит выбранный
- mov esi,[ebx+QUERY_SERVICE_CONFIG.lpDependencies]
- loc_enum_depends:
- cmp word [esi],0
- je loc_no_more_depends
- ; Получить название сервиса
- mov [tmp],100h
- invoke GetServiceDisplayName,[scm],esi,depend,tmp
- ...
- ...
- ; Следующий сервис
- invoke lstrlen,esi
- inc eax
- shl eax,1
- add esi,eax
- jmp loc_enum_depends
- loc_no_more_depends:
Code (Assembler) : Убрать нумерацию
- ; Определить необходимый размер памяти
- invoke EnumDependentServices,[hService],\
- SERVICE_STATE_ALL,0,[BytesNeeded],\
- BytesNeeded,DServicesReturned
- cmp [BytesNeeded],0
- je loc_no_depends
- ; Выделить память
- invoke GlobalAlloc,GMEM_FIXED+GMEM_ZEROINIT,[BytesNeeded]
- mov [mem],eax
- invoke GlobalLock,eax
- mov [Depends],eax
- ; Получить список зависимостей
- invoke EnumDependentServices,[hService],\
- SERVICE_STATE_ALL,[Depends],[BytesNeeded],\
- BytesNeeded,ServicesReturned
- mov ebx,[Depends]
- loc_depends:
- ; EBX -> указатель на структуру ENUM_SERVICE_STATUS
- ...
- ...
- ; Следующий сервис
- add ebx,sizeof.ENUM_SERVICE_STATUS
- ; Все сервисы отработали?
- dec [ServicesReturned]
- cmp [ServicesReturned],0
- ja loc_depends
- ; Освободить память
- invoke GlobalUnlock,[Depends]
- invoke GlobalFree,[mem]
- loc_no_depends:
Приостановить или возобновить работу сервиса, а также полностью остановить его можно при помощи функции ControlService. Сервис должен быть предварительно открыт с правами SERVICE_PAUSE_CONTINUE и/или SERVICE_STOP в зависимости от задачи.
Code (Assembler) : Убрать нумерацию
- ; Открыть сервис
- invoke OpenService,[scm],sname,SERVICE_STOP
- or eax,eax
- jz loc_error
- mov [hService],eax
- ; Остановить сервис
- invoke ControlService,[hService],SERVICE_CONTROL_STOP
- or eax,eax
- jz loc_error
- ; Закрыть сервис
- invoke CloseServiceHandle,[hService]
Code (Assembler) : Убрать нумерацию
- ; Открыть сервис
- invoke OpenService,[scm],sname,SERVICE_START
- or eax,eax
- jz loc_error
- mov [hService],eax
- ; Запустить сервис
- invoke StartService,[hService],0,NULL
- or eax,eax
- jz loc_error
- ; Закрыть сервис
- invoke CloseServiceHandle,[hService]
Code (Assembler) : Убрать нумерацию
- ; Выделить память
- invoke GlobalAlloc,GMEM_FIXED+GMEM_ZEROINIT,sizeof.SERVICE_STATUS
- mov [mem],eax
- invoke GlobalLock,eax
- mov [Status],eax
- ; Получить статус сервиса после запуска
- invoke QueryServiceStatus,[hService],[Status]
- or eax,eax
- jz loc_error
- mov ebx,[Status]
- ; Получить текущее время и контрольную точку сервиса
- invoke GetTickCount
- mov [TickCount],eax
- mov eax,[ebx+SERVICE_STATUS.dwCheckPoint]
- mov [CheckPoint],eax
- start_service_wait:
- ; Сервис в процессе запуска?
- cmp [ebx+SERVICE_STATUS.dwCurrentState],SERVICE_START_PENDING
- jne start_service_done
- ; Сервису требуется время для запуска
- mov eax,[ebx+SERVICE_STATUS.dwWaitHint]
- xor edx,edx
- mov ecx,10
- div ecx
- ; Берем 1/10 часть от запрошенного времени, но не менее
- ; 1 секунды и не более 10 секунд
- cmp eax,1000
- ja @f
- mov eax,1000
- @@:
- cmp eax,10000
- jb @f
- mov eax,10000
- @@:
- invoke Sleep,eax
- ; Получить статус сервиса
- invoke QueryServiceStatus,[hService],[Status]
- ; Контрольная точка изменилась?
- mov eax,[ebx+SERVICE_STATUS.dwCheckPoint]
- cmp eax,[CheckPoint]
- jbe @f
- ; Да, обновить таймер и сохраненную контрольную точку
- invoke GetTickCount
- mov [TickCount],eax
- mov eax,[ebx+SERVICE_STATUS.dwCheckPoint]
- mov [CheckPoint],eax
- jmp start_service_wait
- @@:
- ; Время ожидания превысило запрошенный сервисом таймаут?
- invoke GetTickCount
- sub eax,[TickCount]
- cmp eax,[ebx+SERVICE_STATUS.dwWaitHint]
- jb start_service_wait
- start_service_done:
- ; Сервис запущен?
- cmp [ebx+SERVICE_STATUS.dwCurrentState],SERVICE_RUNNING
- jne loc_error
Code (Assembler) : Убрать нумерацию
- ; Открыть сервис
- invoke OpenService,[scm],sname,DELETE
- or eax,eax
- jz loc_error
- mov [hService],eax
- ; Отметить сервис на удаление
- invoke DeleteService,[hService]
- ; Закрыть сервис
- invoke CloseServiceHandle,[hService]
Code (Assembler) : Убрать нумерацию
- ; Открыть сервис
- invoke OpenService,[scm],sname,SERVICE_CHANGE_CONFIG
- or eax,eax
- jz loc_error
- mov [hService],eax
- ; Заблокировать базу
- invoke LockServiceDatabase,[scm]
- mov [ScLock],eax
- ; Отключить сервис
- invoke ChangeServiceConfig,[hService],SERVICE_NO_CHANGE,\
- SERVICE_DISABLED,SERVICE_NO_CHANGE,\
- NULL,NULL,NULL,NULL,NULL,NULL,NULL
- ; Закрыть сервис
- invoke CloseServiceHandle,[hService]
- ; Разблокировать базу
- invoke UnlockServiceDatabase,[ScLock]
Code (Assembler) : Убрать нумерацию
- ; Получить необходимый размер памяти
- invoke QueryServiceLockStatus,[scm],NULL,0,BytesNeeded
- add [BytesNeeded],100
- ; Выделить память
- invoke GlobalAlloc,GMEM_FIXED+GMEM_ZEROINIT,[BytesNeeded]
- mov [mem],eax
- invoke GlobalLock,eax
- mov [LockDB],eax
- lock_database_wait:
- ; Получить статус блокировки базы
- invoke QueryServiceLockStatus,[scm],[LockDB],[BytesNeeded],tmp
- mov eax,[LockDB]
- cmp [eax+QUERY_SERVICE_LOCK_STATUS.fIsLocked],0
- je lock_database_done
- invoke Sleep,1000
- jmp lock_database_wait
- lock_database_done:
- ; Освободить память
- invoke GlobalUnlock,[LockDB]
- invoke GlobalFree,[mem]
- ; Заблокировать базу
- invoke LockServiceDatabase,[scm]
- mov [ScLock],eax
- ...
- ; Какие-то действия с сервисами
- ...
- ; Разблокировать базу
- invoke UnlockServiceDatabase,[ScLock]
В приложении примеры программ с исходными текстами, одна из которых выводит список установленных сервисов с их конфигурацией, а вторая позволяет управлять выбранным сервисом. Запускать ТОЛЬКО от админа.
Просмотров: 1721 | Комментариев: 15
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
morgot
(18.06.2021 в 00:36):
asm0rot, поставь ХР и изучай матчасть там или же запускай от админа (!). В плане не от юзера админа, а правой кнопкой - "запуск от имени администратора".
asm0rot
(06.06.2021 в 20:09):
У меня стоит USER и он администратор а все равно не хочет грузиться что такое...
ManHunter
(06.06.2021 в 19:14):
Запускать ТОЛЬКО от админа.
asm0rot
(06.06.2021 в 19:11):
; Открыть менеджер сервисов
invoke OpenSCManager,NULL,NULL,SC_MANAGER_ALL_ACCESS
возвращает ERROR_ACCESS_DENIED (00000005) что делать?
invoke OpenSCManager,NULL,NULL,SC_MANAGER_ALL_ACCESS
возвращает ERROR_ACCESS_DENIED (00000005) что делать?
_sheva740
(02.06.2021 в 21:40):
Спасибо ребята!!!
ManHunter
(29.05.2021 в 11:17):
DRON, опять выручаешь :) Спасибо! Статью подкорректировал, архив обновлен.
DRON
(28.05.2021 в 23:51):
QUERY_SERVICE_CONFIG содержит полный список сервисов, но в формате "doubly null-terminated strings" то есть за первой строкой сразу идёт вторая, а за последней идёт ещё один нолик.
Ссылка по теме: https://devblogs.microsoft.com...-00/?p=14883
Ну а вызовы Lock/UnlockServiceDatabase после XP просто игнорируется. Насколько я помню их убрали как раз из-за неправильного использования большинством разработчиков.
_sheva740: Битность сервиса определяется по битности кода вызвавшего CreateService. Если вы вызываете CreateService из 32-х битного приложения запущенного на 64-х битной системе (что типично для инсталляторов), то сервис помечается как 32-х битный (создаётся параметр WOW64 в соответствующей ветке реестра) независимо от разрядности самого сервиса.
Ссылка по теме: https://devblogs.microsoft.com...-00/?p=14883
Ну а вызовы Lock/UnlockServiceDatabase после XP просто игнорируется. Насколько я помню их убрали как раз из-за неправильного использования большинством разработчиков.
_sheva740: Битность сервиса определяется по битности кода вызвавшего CreateService. Если вы вызываете CreateService из 32-х битного приложения запущенного на 64-х битной системе (что типично для инсталляторов), то сервис помечается как 32-х битный (создаётся параметр WOW64 в соответствующей ветке реестра) независимо от разрядности самого сервиса.
morgot
(28.05.2021 в 18:52):
Спасибо, хорошая статья! Именно вот мануал от и до по службам.
Единственное - касаемо зависимых сервисов. Вроде как QUERY_SERVICE_CONFIG содержит сервисы, от которых зависит текущий (их надо запустить перед ним); а вот EnumDependentServices перечисляет сервисы, зависимые от текущего (его надо запускать перед ними, или при завершении - сначала их).
Могу ошибаться! Хорошая тулза для работы со службами - Process Haker.
Единственное - касаемо зависимых сервисов. Вроде как QUERY_SERVICE_CONFIG содержит сервисы, от которых зависит текущий (их надо запустить перед ним); а вот EnumDependentServices перечисляет сервисы, зависимые от текущего (его надо запускать перед ними, или при завершении - сначала их).
Могу ошибаться! Хорошая тулза для работы со службами - Process Haker.
Exit
(28.05.2021 в 13:18):
ManHunter, Спасибо, поюзаю, на досуге)
ManHunter
(27.05.2021 в 23:22):
Конечно можно. Например, тот же nnCron, Apache2, все проверено, все работает.
_sheva740
(27.05.2021 в 22:45):
Извините за неточность.
Вопрос - можно ли писать сервис 32-х битный и потом зарегистрировать этот сервис в OS Win10 x64?
Спасибо.
Вопрос - можно ли писать сервис 32-х битный и потом зарегистрировать этот сервис в OS Win10 x64?
Спасибо.
ManHunter
(27.05.2021 в 22:14):
Ну вот, а я только телепатов в отпуск отправил. "он" - это кто? "зарегистрируется в системе" - это что?
_sheva740
(27.05.2021 в 15:54):
Спасибо!
А под Win10 x64 разве он зарегистрируется в системе?
А под Win10 x64 разве он зарегистрируется в системе?
ManHunter
(26.05.2021 в 14:40):
Офсайта нет, брал где-то давным-давно, уже и не вспомню.
https://www.upload.ee/files/13...0.6.zip.html
В архиве оригинал и мой исправленный вариант. Пропатчены права доступа и исправлены ресурсы. Но остались косяки, которые патчем не поправить, только переписывать все нафиг.
https://www.upload.ee/files/13...0.6.zip.html
В архиве оригинал и мой исправленный вариант. Пропатчены права доступа и исправлены ресурсы. Но остались косяки, которые патчем не поправить, только переписывать все нафиг.
Exit
(26.05.2021 в 14:35):
ManHunter, а у проги есть сайт?
А то погуглил и не нашел...
Хоть глянуть, что за зверь:)
P.S. раньше, когда "воевал" со службами, юзал gtools
http://p-nand-q.com/download/p...l/index.html
А на Семерке, выпиливаю NTLite'ом
Нет файлов = нет процессов = нет дыр:)
Добавить комментарий
Заполните форму для добавления комментария