Win Service - OK on XP 32-bit, dead on Win 7 32-bit???

Started by Astro, January 29, 2010, 11:24:24 AM

Previous topic - Next topic

Astro

Hi,

I'll post the code momentarily, but for some reason, whilst it installs OK, my service is dead, and terminates immediately?

I'm not aware of any differences in the service code requirements as I wrote it only last year, Vista was out (obviously) and didn't appear to have special requirements, and neither did Win 7.

As a result, I've no idea where it may be failing, or why. I tried to debug it, but it was unclear what was happening.

Anyone aware of any differences or special handling required for Vista/Win 7 32-bit??

Best regards,
Robin.

Astro

Hi,

Edited for brevity, but the core code is intact.

.386
.model flat,stdcall

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\advapi32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\user32.lib

.data?
hProcHeap dword ?
ServiceTable dword ? ; http://msdn.microsoft.com/en-us/library/ms686001(VS.85).aspx
hServiceStatus dword ?
ServiceStatus dword ? ; http://msdn.microsoft.com/en-us/library/ms685996(VS.85).aspx
;=======================================================

.code
ServiceName db "Test Service",0
;=======================================================
align 4

start:

call GetProcessHeap
mov hProcHeap,eax

push 16
push 8h
push hProcHeap
call HeapAlloc
mov ServiceTable,eax

push 28
push 8h
push hProcHeap
call HeapAlloc
mov ServiceStatus,eax

mov edx,ServiceTable
mov dword ptr [edx],offset ServiceName
mov dword ptr [edx+4],offset ServiceMain
mov dword ptr [edx+8],NULL
mov dword ptr [edx+12],NULL

push ServiceTable
call StartServiceCtrlDispatcher ; http://msdn.microsoft.com/en-us/library/ms686324(VS.85).aspx

;---------------------------------------------
; Clean up and exit
cleanup:

push ServiceTable
push 0h
push hProcHeap
call HeapFree

push ServiceStatus
push 0h
push hProcHeap
call HeapFree

ret 4
;===========================================================

ServiceMain proc
push 0h
push offset ServiceMsgHandler
push offset ServiceName
call RegisterServiceCtrlHandlerEx
mov hServiceStatus,eax

;---------------------------------------------
; Initialize ServiceStatus structure

mov edx,ServiceStatus
mov dword ptr [edx],10h ; dwServiceType - SERVICE_WIN32_OWN_PROCESS
mov dword ptr [edx+4],SERVICE_START_PENDING ; dwCurrentState
mov dword ptr [edx+8],0 ;SERVICE_ACCEPT_STOP ; dwControlsAccepted - stop/pause/restart
mov dword ptr [edx+12],0h ; dwWin32ExitCode
mov dword ptr [edx+16],0h ; dwServiceSpecificExitCode
mov dword ptr [edx+20],0h ; dwCheckPoint - increment for every subsequent START_PENDING update to reset time-out
mov dword ptr [edx+24],15000 ; dwWaitHint - 30 second time-out for next operation and subsequent call to SetServiceStatus

push ServiceStatus
push hServiceStatus
call SetServiceStatus ; http://msdn.microsoft.com/en-us/library/ms686241(VS.85).aspx

;---------------------------------------------
; Initialize service

; do more config here for the actual service function including loading of 3rd party libs

mov edx,ServiceStatus
mov dword ptr [edx+4],SERVICE_RUNNING ; dwCurrentState
mov dword ptr [edx+20],0h ; dwCheckPoint - increment for every subsequent START_PENDING update to reset time-out
mov dword ptr [edx+24],0 ; dwWaitHint - 30 second time-out for next operation and subsequent call to SetServiceStatus
push ServiceStatus
push hServiceStatus
call SetServiceStatus ; http://msdn.microsoft.com/en-us/library/ms686241(VS.85).aspx

; we told SCM we are now up and running
; enter the actual service routine

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MAIN_SERVICE_LOOP:

; perform actual service functions here

push 5000 ; we run our service function every 5 seconds
call Sleep

; these next lines look to see if we've been told to stop running
mov edx,ServiceStatus
cmp dword ptr [edx+4],SERVICE_STOPPED
jnz MAIN_SERVICE_LOOP
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

; we are to stop running via SCM so lets exit
ret 8h

ServiceMain endp

end start


Build the above as a normal console .EXE project. You need some way to add this to the SCM before running. See the following code. Build it separately as a console app.

Service Installer (works on all platforms):

.386
.model flat,stdcall

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\advapi32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\advapi32.lib

.data?
hSCManager dword ?
hLib dword ?
lasterr dword ?
path db 260 dup (?)

.code
ServiceName db "Service Name",0
lib db ".\service.exe",0 ; ****** CHANGE THIS TO MATCH THE EXE BUILT ABOVE ******
align 4

start:

;---------------------------------------------
; Get path of current thread executable (this service installer EXE)
; Used to define path for Service Manager

push offset lib
call LoadLibrary
mov hLib,eax

push MAX_PATH
push offset path
push hLib
call GetModuleFileName

push hLib
call FreeLibrary

call GetLastError
cmp eax,ERROR_INSUFFICIENT_BUFFER
jnz @F

; Error - quit
ret
;===========================================================

@@:
push SC_MANAGER_ALL_ACCESS
push 0h
push 0h
call OpenSCManager
mov hSCManager,eax

cmp eax,0h
jnz @F

; Error - quit
ret
;===========================================================

@@:
push 0h
push 0h
push 0h
push 0h
push 0h
push offset path
push SERVICE_ERROR_IGNORE
push SERVICE_AUTO_START
push SERVICE_WIN32_OWN_PROCESS
push SC_MANAGER_ALL_ACCESS
push offset ServiceName
push offset ServiceName
push hSCManager
call CreateService

cmp eax,0h
jnz @F

; CreateService failed - exit
push hSCManager
call CloseServiceHandle
ret
;===========================================================

@@:
push hSCManager
call CloseServiceHandle
xor eax,eax
ret

end start


Best regards,
Robin.

ecube

I don't see any issues with the above, the main changes i've seen for services on vista+ is you're not allowed to do any UI stuff, messageboxes, windows etc... reason being is stupid skiddies kept writting code that does something called shatter attacks, where windows messages makes a process do somethin, usually privledge escalation. Alternatively you have have to do different kind of IPC, using sockets, pipes, mapped files, etc... I am gonna try your code on win7 though.