Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Любителям "скырть процесс" под NT посвящается...


Страницы:   1 2 3

Игорь Шевченко ©   (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);
.........


BiN   (2005-02-02 11:13:00) [41]

вдогонку к
BiN ©   (02.02.05 10:46) [6]

Правда, тут могут начаться "гонки" с перехватом NtCreateFile и т.п., но это уже из другой оперы...


Имеется ввиду также перехват остальных функций I/O файловой системы.


Игорь Шевченко   (2005-02-02 11:12:00) [42]

BiN ©   (02.02.05 11:09) [10]

Разумеется, NtCreateFile + NtCreateSection. Но дело в том, что если перехватить, то как тогда остальные будут работать ? Ведь любая программа отображает NTDLL на свое адресное пространство.

С уважением,


BiN   (2005-02-02 11:09:00) [43]

Игорь Шевченко ©   (02.02.05 10:57) [7]

А зачем перехватывать NtCreateFile ? Я, честно говоря, смысла не вижу.


А с помощью каких функций считывается PE-заголовок ntdll.dll?


kaZaNoVa   (2005-02-02 11:09:00) [44]

ура, пример работает!!!
//проверял пока только одну функцию - детектор перехвата IsNtDllHooked- потрясающе))


kaZaNoVa   (2005-02-02 11:04:00) [45]

BiN ©   (02.02.05 10:46) [6]
всё равно всё не перехватят))
95% имхо всех "перехватчиков" останавливаются на том, что не видны в таск-манагере и всё)))


Игорь Шевченко   (2005-02-02 10:57:00) [46]

BiN ©   (02.02.05 10:46) [6]

А зачем перехватывать NtCreateFile ? Я, честно говоря, смысла не вижу.

С уважением,


BiN   (2005-02-02 10:46:00) [47]

Правда, тут могут начаться "гонки" с перехватом NtCreateFile и т.п., но это уже из другой оперы...


BiN   (2005-02-02 10:43:00) [48]

Игорь Шевченко ©   (02.02.05 10:40) [4]

Проверяется соответствие как правленной IAT, так и совпадения кода по адресу NtQuerySystemInformation в загруженной DLL и на диске

(выделение мое)

Точно, не обратил внимание на эту строку:

Image := THSPEImage.Create (FileName);


в функции IsNtDllCodeHooked


Игорь Шевченко   (2005-02-02 10:40:00) [49]

BiN ©   (02.02.05 10:25) [1]

Привет! Данный код как раз служит для вытаскивания за ушко и на солнышко процессов, которые пользуются методом внедрения без правки IAT, а установкой в адресном пространстве "жертвы" кода перехода на свою скрывающую функцию по корректному адресу в NTDLL.DLL

Краткий алгоритм такой: Проверяется соответствие как правленной IAT, так и совпадения кода по адресу NtQuerySystemInformation в загруженной DLL и на диске. Если код не совпадает, то для вызова функции используется тот код, который в файле NTDLL.DLL на диске находится.

С уважением,


kaZaNoVa   (2005-02-02 10:37:00) [50]

BiN ©   (02.02.05 10:25) [1]
имхо обычно ориентируемся на самые часто-испрользуемые способы перехвата и их отлавливаем .))

//ща тестирую, результаты сообщу))


BiN   (2005-02-02 10:30:00) [51]

Или я чего-то недопонимаю в коде(?)....


BiN   (2005-02-02 10:25:00) [52]

Игорь, приветствую!

Ты наверняка сам знаешь, что перехват можно осуществлять не только правкой IAT.

С уважением.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо