![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Любителям "скырть процесс" под NT посвящается...
Игорь Шевченко © (2005-02-02 10:21:00)Небольшой код, позволяющий определить, есть ли в системе потенциально вредоносный процесс, скрывающий себя от Task Manager'а, Process Explorer'а и прочих просмотрщиков списка процессов. В сочетании с включенным аудитом процессов поможет выявить поделки доморощенных пакостников.
Проверено на Windows 2000 и Windows XP.
unit CheckNtDll;
interface
uses
Windows, HsNtDef;
function RealQueryListInformation (InfoClass: Integer; var rc: NTSTATUS;
var ReturnLength: DWORD): Pointer;
function IsNtDllHooked: Boolean;
implementation
uses
SysUtils, NtDll, PeImage, NtStatusDefs;
{$IFDEF VER140}
{$WARN SYMBOL_PLATFORM OFF}
{$ENDIF}
type
TSysCallData = array[0..13] of Byte;
TNtQuerySystemInformation = function (SystemInformationClass: LongInt;
SystemInformation: Pointer; SystemInformationLength: ULONG;
ReturnLength: PDWORD): NTSTATUS; stdcall;
var
FRealQuerySystemInformation: TNtQuerySystemInformation;
function RealQueryListInformation (InfoClass: Integer; var rc: NTSTATUS;
var ReturnLength: DWORD): Pointer;
var
ListSize: Integer;
begin
ListSize := $400; { Начальный размер буфера }
GetMem(Result, ListSize);
rc := FRealQuerySystemInformation(InfoClass, Result, ListSize, @ReturnLength);
while rc = STATUS_INFO_LENGTH_MISMATCH do begin
FreeMem(Result);
ListSize := ListSize * 2;
GetMem(Result, ListSize);
rc := FRealQuerySystemInformation(InfoClass, Result, ListSize,
@ReturnLength);
end;
if rc <> STATUS_SUCCESS then begin
FreeMem(Result);
Result := nil;
end;
end;
procedure MakeRealQS (const SysCallData: TSysCallData);
var
OldProtection: DWORD;
FuncPtr: Pointer;
begin
FuncPtr := VirtualAlloc(nil, $1000, MEM_COMMIT, PAGE_READWRITE);
Win32Check(Assigned(FuncPtr));
Move(SysCallData, FuncPtr^, SizeOf(SysCallData));
Win32Check(VirtualProtect(FuncPtr, SizeOf(SysCallData), PAGE_EXECUTE,
OldProtection));
@FRealQuerySystemInformation := FuncPtr;
end;
function IsNtDllCodeHooked (const FileName: string; ProcOffset: ULONG): Boolean;
var
Image: THSPeImage;
SysCall: TSysCallData;
SysCall2: TSysCallData;
QSPtr: Pointer;
begin
Image := THSPEImage.Create (FileName);
try
Move(Image.RVAData[ProcOffset]^, SysCall, SizeOf(SysCall));
finally
Image.Free;
end;
QSPtr := GetProcAddress(GetModuleHandle('ntdll.dll'),
'NtQuerySystemInformation');
Move(QSPtr^, SysCall2, SizeOf(SysCall2));
Result := not CompareMem(@SysCall, @SysCall2, SizeOf(SysCall));
if Result then
MakeRealQS (SysCall);
end;
function IsNtDllHooked: Boolean;
const
SDllPath = '%SystemRoot%\system32\ntdll.dll';
var
DllPath: ZString;
HFile, HMap: THandle;
Map: Pointer;
Headers: PImageNtHeaders;
QSysInfo: Pointer;
begin
Result := false;
Win32Check(
ExpandEnvironmentStringsA(SDllPath, DllPath, SizeOf(DllPath)) <> 0);
HFile := CreateFileA(DllPath, GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
Win32Check(HFile <> INVALID_HANDLE_VALUE);
try
HMap := CreateFileMappingA(HFile, nil, PAGE_READONLY, 0, 0, nil);
Win32Check(HMap <> 0);
try
Map := MapViewOfFile(HMap, FILE_MAP_READ, 0, 0, 0);
Win32Check(Assigned(Map));
try
Headers := RtlImageNtHeader(HMODULE(Map));
if Assigned(Headers) then
Result :=
Headers.OptionalHeader.ImageBase <> GetModuleHandle('ntdll.dll');
if not Result then begin
QSysInfo := GetProcAddress(GetModuleHandle('ntdll.dll'),
'NtQuerySystemInformation');
if Assigned(QSysInfo) then begin
Result := (Cardinal(QSysInfo) <=
Headers.OptionalHeader.ImageBase) or (Cardinal(QSysInfo) >
Headers.OptionalHeader.ImageBase +
Headers.OptionalHeader.SizeOfCode);
if not Result then
Result := IsNtDllCodeHooked(DllPath, ULONG(QSysInfo) -
Headers.OptionalHeader.ImageBase);
end else
Result := true;
end;
finally
UnmapViewOfFile(Map);
end;
finally
CloseHandle(HMap);
end;
finally
CloseHandle(HFile);
end;
end;
initialization
finalization
if Assigned(FRealQuerySystemInformation) then
VirtualFree(@FRealQuerySystemInformation, $1000, MEM_DECOMMIT);
end.
Пример использования:
FQueryInformationFunction: TQueryListInformation;
.........
if IsNtDllHooked then begin
ShowMessage('NtDll is hooked!');
@FQueryInformationFunction := @RealQueryListInformation;
end else
@FQueryInformationFunction := @QueryListInformation;
.....
var
ProcessInfo: Pointer;
rc: NTSTATUS;
Dummy: ULONG;
begin
ProcessInfo := FQueryInformationFunction (
SystemProcessesAndThreadsInformation, rc, Dummy);
if NT_SUCCESS(rc) then
ShowProcessList (ProcessInfo)
else
RaiseNtError (rc);
.........
xShadow (2005-02-04 15:48:00) [1]
> Игорь Шевченко © (04.02.05 15:43) [51]
Согласен, перехват WinApi может буть и не в 5 пяти байтах! Поэтому и говорю что может трактоваться. Я думаю что нужен комплекс из нескольких проверок.
Игорь Шевченко (2005-02-04 15:43:00) [2]xShadow © (04.02.05 15:40) [50]
Это не всегда корректно.
xShadow (2005-02-04 15:40:00) [3]Встречал в сети реализации проверки на хуки проверкой 5-и первых байт в IAT на предмет call и jmp что в свою очередь может трактоваться как перехват проверяемой процедуры.
kaZaNoVa (2005-02-04 12:52:00) [4]BiN © (04.02.05 11:51) [45]
> Но зато сабжевый код - отличный способ дать по рукам
> молодым кулхацкерам.
это точно .. терь половина их "разработок" станет бесполезна))
kaZaNoVa (2005-02-04 12:51:00) [5]BiN © (04.02.05 11:51) [45]
> По-моему, остановить из пользовательского режима
> вредоносную программу, особенно работающую в
> админо-подобном контексте, невозможно.
я тоже так думаю ..
особенно, если программа "заточена" для этого - например программа - троян, засланный конкурентами по бизнесу, не знаю, как сейчас - но в буду.щем могу предположить, что в конкурентной борьбе не последнее место будет занимать программы-трояны, засылаемые конкурентам ... -)
BiN (2005-02-04 12:41:00) [6]Игорь Шевченко © (04.02.05 11:57) [46]
Жаба хитра, но маленький хрущ с винтом много хитрее ее.
Я как-то уже писал, что узнать скрытый процесс можно по меньше мере, четырьмя различными способами под Windows 2000 и Windows NT. Под Windows XP к способам добавился еще способ взаимодействия с отладчиком.
Из пользовательского режима можно установить факт наличия скрытого процесса и звать администратора, чтобы он разобрался :)
Согласен :)
И поэтому считаю, что "скрывать процесс" - неблагодарное занятие.
Игорь Шевченко (2005-02-04 11:57:00) [7]BiN © (04.02.05 11:51) [45]
> Так или иначе, реализовать перехват почти всех пользовательских
> процессов можно - пусть с тормозами, пусть геморрно и с
> раздутым кодом - но можно. Достаточно анализировать диапазон
> считываемых данных в NtReadFile и хранить значения описателей
> получаемых при открытии "ntdll.dll".
Жаба хитра, но маленький хрущ с винтом много хитрее ее.
Я как-то уже писал, что узнать скрытый процесс можно по меньше мере, четырьмя различными способами под Windows 2000 и Windows NT. Под Windows XP к способам добавился еще способ взаимодействия с отладчиком.
Из пользовательского режима можно установить факт наличия скрытого процесса и звать администратора, чтобы он разобрался :)
С уважением,
BiN (2005-02-04 11:51:00) [8]Игорь Шевченко © (04.02.05 11:13) [44]
Но откуда перехватчик узнает, что перехватывать надо именно мой процесс ? :))
Так или иначе, реализовать перехват почти всех пользовательских процессов можно - пусть с тормозами, пусть геморрно и с раздутым кодом - но можно. Достаточно анализировать диапазон считываемых данных в NtReadFile и хранить значения описателей получаемых при открытии "ntdll.dll".
По-моему, остановить из пользовательского режима вредоносную программу, особенно работающую в админо-подобном контексте, невозможно.
Но зато сабжевый код - отличный способ дать по рукам молодым кулхацкерам. Если бы еще тема была выложена в виде статьи, то можно было бы по всем смежным вопросам отсылать к ней. На форуме ветка, боюсь, в Лету уйти может.
Игорь Шевченко (2005-02-04 11:13:00) [9]BiN © (03.02.05 16:42) [41]
> Игорь, как, по-твоему, правка адресного пространства одного
> процесса (собственно перехват NtCreateFile, NtReadFile и
> т.п.) может повлиять на работу других процессов, тем более,
> системных?
Нет, конечно не может. Но откуда перехватчик узнает, что перехватывать надо именно мой процесс ? :))
С уважением,
Burmistroff (2005-02-03 23:06:00) [10]Cool :)
Есть програмка - "SDTRestore" и "KProcCheck" - проверяют (и удаляют) различные ухищрения на которые идут rootkit'ы для сокрытия себя. Идея та же - сравнение с оригиналом файла на диске. Правда они для kernel-mode.
Burmistroff (2005-02-03 23:06:00) [11]Cool :)
Есть програмка - "SDTRestore" и "KProcCheck" - проверяют (и удаляют) различные ухищрения на которые идут rootkit'ы для сокрытия себя. Идея та же - сравнение с оригиналом файла на диске.
BiN (2005-02-03 16:42:00) [12]
>>Игорь Шевченко © (02.02.05 11:12) [11]
Но дело в том, что если перехватить, то как тогда остальные будут работать ? Ведь любая программа отображает NTDLL на свое адресное пространство
...
>> [19]
Если перехватывать NtCreateFile, то с какой целью ? Не дать открыть NtDll ? Так это вся система сломается.
...
>> [38]
Так система тоже читает.
Игорь, как, по-твоему, правка адресного пространства одного процесса (собственно перехват NtCreateFile, NtReadFile и т.п.) может повлиять на работу других процессов, тем более, системных?
С уважением,
Игорь Шевченко (2005-02-03 16:26:00) [13]Piter © (03.02.05 15:33) [39]
Все замыкается на NtCreateFile - это единственная дырка. И не читает, а получает доступ к файлу.
С уважением,
Piter (2005-02-03 15:33:00) [14]Игорь Шевченко © (03.02.05 14:12) [38]
Так система тоже читает
А она читает тоже через NtCreateFile? Или через какие-то свои внутренние функции?
Игорь Шевченко (2005-02-03 14:12:00) [15]SammIk © (03.02.05 13:43) [37]
Так система тоже читает. И для того, чтобы она работала, необходимо, чтобы читалось то, что запрошено и данные должны быть верными.
SammIk (2005-02-03 13:43:00) [16]С тавится хук на чтение и открытие фаила.
Если открыли то, что не надо открывать. Можно вернуть
код ошибки, мол нет доступа или еще что.
Если читают то, что не надо, то возвращаем не верную инфу.
И чего тут невозможного?
Игорь Шевченко (2005-02-03 10:43:00) [17]SammIk © (02.02.05 21:20) [35]
Я бы все-таки хотел увидеть, каким образом хук на NtCreateFile может одновременно помешать мне открыть нужныйфайл и в то же время гарантировать работу других приложений.
С уважением,
SammIk (2005-02-02 21:20:00) [18]Респект Игорь Шевченко ©.
Все круто, но есть одно но.
Ежели будет стоять хук на NtCreateFileEx, то соответственно
можно будет отловить обращение к хукнутым библиям и вернуть
то, что это детектор хочет.
Есть другой вариант.
Конкретно для kernel32
Через SEH получить базу образа, там в импортах найти куда идти дальше.
Если в импорт ссылается на адрес вне (imgbase,imgbase+imgsiz)
то делаем вывод, что нас прохучили по импорту.
Ежели все в порядке, то проверяем на предмет джампов саму ф-ю
по тойже схеме.
------
Хотя и такой пример работает)
------
Способ для извращенцев, но действенный.
Открывать винт на чтение, искать нужный фаил, и далее как
Игорь делать
Игорь Шевченко (2005-02-02 17:06:00) [19]
> Но что это такое и что будет, если включить - не понял.
F1
Piter (2005-02-02 17:04:00) [20]Игорь Шевченко © (02.02.05 16:12) [29]
Локальная политика безопасности + F1
Открыл справку, посмотрел. Вот что у меня:
Администрирование
Службы компонентов
Управление компьютером
Источники данных (ODBC)
Окно просмотра событий
Локальная политика безопасности
Системный монитор
Службы
Нигде про аудит процессов не нашел :(
Хочу оговориться, что у меня w2k.
В политиках аудита нашел "Аудит отслеживания процессов". Но что это такое и что будет, если включить - не понял.