在找到this useful question之后,我可以创建一个应用程序作为Windows服务进行成功。
然后,我创建了一个单独的可执行文件来将我的应用程序作为服务执行,但我的应用程序没有被执行。
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.