将应用程序作为服务运行:开始挂起

时间:2016-06-17 03:23:20

标签: delphi service

在找到this useful question之后,我可以创建一个应用程序作为Windows服务进行成功。

然后,我创建了一个单独的可执行文件来将我的应用程序作为服务执行,但我的应用程序没有被执行。

enter image description here

Flsh_Service.exe 是执行 Start_Dll.exe 的单独可执行文件

这是我的应用程序应该可以工作,但失败了。

所以我问:

  

为什么我的应用程序未作为服务正确执行?

与上面提到的问题有关, cmd.exe 这里是注入目标,应用程序作为服务运行: Start_Dll.exe (上面提到的问题是 cmd.exe )。

program Start_Dll;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Winapi.windows,
  CreateProcessIntr,
  vcl.forms,
  Winapi.messages,
  shellapi,
  tlhelp32;

Const SE_DEBUG_NAME = 'SeDebugPrivilege';

procedure GetDebugPrivs;
var
  hToken: THandle;
  tkp: TTokenPrivileges;
  retval: dword;
begin
 if  (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or  TOKEN_QUERY, hToken)) then
   begin
     LookupPrivilegeValue(nil, SE_DEBUG_NAME, tkp.Privileges[0].Luid);
     tkp.PrivilegeCount := 1;
     tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
     AdjustTokenPrivileges(hToken, false, tkp, 0, nil, retval);
   end;
end;

procedure InjectDLL(const ADLLName: AnsiString; targetproc: Cardinal);
var
  dllname: AnsiString;
  pDLLname, pStartAddr: Pointer;
  bw: NativeUInt;
  hProcess, hRemoteThread: THandle;
  TID: Cardinal;
begin
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, false, targetproc);
  pDLLname := VirtualAllocEx(hProcess, 0, length(dllname) + 1,
    MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);

  WriteProcessMemory(hProcess, pDLLname, Pointer(dllname),
    length(dllname) + 1, bw);

  pStartAddr := GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryW');
  hRemoteThread := CreateRemoteThread(hProcess, nil, 0, pStartAddr,
    pDLLname, 0, TID);
  WaitForSingleObject(hRemoteThread, INFINITE);
  CloseHandle(hProcess);
end;

function search(name:string): Cardinal;
var ExeFile    : String;
    PE         : TProcessEntry32;
    FSnap: THandle;
begin
 result:= 0;
 FSnap:= Tlhelp32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

 PE.dwSize:= SizeOf(PE);
 if (Tlhelp32.Process32First(FSnap,PE)) Then
  Repeat
   ExeFile:= PE.szExeFile;

   if pos(pchar(lowercase(name)), lowercase(ExeFile))>0 then
    Begin
     result:= PE.th32ProcessID;
     break
    End;
   Until Not Process32Next(FSnap,PE)
end;

var
   PID: Dword;
   dll_to_inject: AnsiString;
   Process: String;

////////////////////////////////////////////////////////////////////////////////

begin
 {Sleep(120000);}

 //GetDebugPrivs;

 dll_to_inject:=ExtractFilePath(application.ExeName) + 'myDLL.dll;

 Process:= 'cmd.exe';

 ExecuteProcessAsLoggedOnUser(Process);

 PID:=search(PROCESS);

 if PID=0 then begin
  exit;
 end;

 InjectDll(dll_to_inject, PID);

end.

CreateProcessIntr.pas

unit CreateProcessIntr;

interface

uses
  Windows, SysUtils, Registry, TlHelp32;

procedure ExecuteProcessAsLoggedOnUser(FileName: string);

implementation

function GetShellProcessName: string;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_READ);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    Reg.OpenKeyReadOnly('Software\Microsoft\Windows NT\CurrentVersion\WinLogon');
    Result := Reg.ReadString('Shell');
  finally
    Reg.Free;
  end;
end;

function GetShellProcessPid(const Name: string): Longword;
var
  Snapshot: THandle;
  Process: TProcessEntry32;
  B: Boolean;
begin
  Result := 0;
  Snapshot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Snapshot <> INVALID_HANDLE_VALUE then
  try
    FillChar(Process, SizeOf(Process), 0);
    Process.dwSize := SizeOf(Process);
    B := Process32First(Snapshot, Process);
    while B do
    begin
      if CompareText(Process.szExeFile, Name) = 0 then
      begin
        Result := Process.th32ProcessID;
        Break;
      end;
      B := Process32Next(Snapshot, Process);
    end;
  finally
    CloseHandle(Snapshot);
  end;
end;

function GetShellHandle: THandle;
var
  Pid: Longword;
begin
  Pid := GetShellProcessPid(GetShellProcessName);
  Result := OpenProcess(PROCESS_ALL_ACCESS, False, Pid);
end;

procedure ExecuteProcessAsLoggedOnUser(FileName: string);
var
  ph: THandle;
  hToken, nToken: THandle;
  ProcInfo: TProcessInformation;
  StartInfo: TStartupInfo;
begin
  ph := GetShellHandle;
  if ph > 0 then
  begin
    if OpenProcessToken(ph, TOKEN_DUPLICATE or TOKEN_QUERY, hToken) then
    begin
      if DuplicateTokenEx(hToken, TOKEN_ASSIGN_PRIMARY or TOKEN_DUPLICATE or TOKEN_QUERY,
        nil, SecurityImpersonation, TokenPrimary, nToken) then
      begin
        if ImpersonateLoggedOnUser(nToken) then
        begin
          // Initialize then STARTUPINFO structure
          FillChar(StartInfo, SizeOf(TStartupInfo), 0);
          StartInfo.cb := SizeOf(TStartupInfo);
          StartInfo.dwFlags := STARTF_USESHOWWINDOW;
          StartInfo.wShowWindow := 0;
          // Specify that the process runs in the interactive desktop
          StartInfo.lpDesktop := PChar('WinSta0\Default');

          // Launch the process in the client's logon session
          CreateProcessAsUser(nToken, nil, PChar(FileName), nil, nil, False,
            CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartInfo, ProcInfo);

          // End impersonation of client
          RevertToSelf();
        end;
        CloseHandle(nToken);
      end;
      CloseHandle(hToken);
    end;
  end;
end;

end.

0 个答案:

没有答案