Авторы: Shearer и Dreg
Переводчик: Izg0y
Оригинал (EN): www.phrack.org
phook - The PEB Hooker
------[ 0.- Предисловие
Номенклатуры:- [T.Index]: соответствующих работ (section 10).
- [R.Index]: ссылки (section 11).
Индекс это идентификатор из номенклатуры.
Для понимания документа требуются знания по win32:- Форматы исполняемых файлов:
- Программирование:
- Использование APIs [R.20]: LoadLibrary, GetModuleHandle ...
- Hooks [R.10] [R.8] [...]
- Win32 ASM [R.21].
Термины которые часто используются в документе:- DLL_FAKE: DLL которая будет подменять системную DLL (DLL_REAL).
- DLL_REAL: DLL которая будет подменяться DLL_FAKE.
Если неуказанно иначе, hook/s будет всегда ссылаться на hook/s в win32.
------[ 1.- Введение
Перехват в win32 обычно используются для обратного проектирования, обычно для анализа работы malware и пакеров, систем защиты программного обеспечения.
Перехват также используются для наблюдения за действиями части программ: доступ к файлам, сокетам, модификацией реестра и т д...
Большинство известных методов реализации перехвата под ring3 (см. пункт 2.5) имеют различные проблемы (см. пункт 2.5.1). Наиболее актуальная для нас заключается в том, что специальные программы могут обнаружить их...
Некоторые защитные программы (фаерволы, антивирусы, антируткиты и т. д.), в состоянии приостановить поток, снять неизвестные ей перхваты и продолжить нормальное выполнение потока.
Другая проблема возникает при попытке реализовать перехват в вирусе, который отслеживает API адреса в памяти, отключая такие типы перехвата, как IAT HOOKING (см. пункт 2.5). Есть так же защитное ПО использующие вирусные
технологии и наоборот.
Из-за этих проблем мы создали phook, который использует несколько документированных методов при реализации перехвата в ring3 и даже реализует некоторые вирусные технологи используя наш перехват.
Этот документ объясняет как работает phook и PEB HOOKING [T.1].
phook - это инструмент, который использует PEB PEB HOOKING [T.1] для реализации перехвата в DLL, он также позволяет реализовать другие задачи в интерактивном режиме:- Показать список загружаемых модулей.
- Загрузить DLL.
- Скачать DLL.
- ...
PEB HOOKING [T.1] выполняет замену DLL_REAL в памяти на DLL_FAKE, поэтому все модули процесса, которые используют DLL_REAL теперь будут использовать DLL_FAKE.
------[ 2 - Предыдущая концепций
Для понимания работы PEB HOOKING [T.1] метода и phook, необходимо четко понимать некоторые понятия.
------[ 2.1 - Process Environment Block
Process Environment Block (PEB) это структура [R.1] расположенная в пользовательском пространстве, которая содержит данные окружающей среды процесса : [R.2]:- Переменные среды.
- Список загруженных модулей.
- Адреса в памяти Heap.
- If the process is being depurated.
- ...
Code:
typedef struct _PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PPEBLOCKROUTINE FastPebLockRoutine;
PPEBLOCKROUTINE FastPebUnlockRoutine;
...
} PEB, *PPEB;
Для реализации PEB HOOKING, нужно использовать поле LoaderData [T.1].
------[ 2.1.1 - LoaderData
Оно представляет собой структуру [R.1], в которой есть данные о модулях в процессе. Это двойной связанный список, и он может быть отсортированы по трём критериям [R.2]:- Порядок загрузки
- Порядок в памяти
- Порядок инициализации
Code:
typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
Все flink и blink поля в LIST_ENTRY указывает на LDR_MODULE.
Code:
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY * Flink;
struct _LIST_ENTRY * Blink;
} LIST_ENTRY,*PLIST_ENTRY;
Данные, которые нам понадобятся из LDR_MODULE, реализовывая PEB HOOKING это [T.1]:- BaseAddress: Адрес модуля в памяти..
- EntryPoint : Адрес где содержится первая инструкция для выполнения модуля.
- SizeOfImage: Размер модуля в памяти.
Code:
typedef struct _LDR_MODULE
{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
------[ 2.2 - Import Address Table
Import Address Table (IAT) это таблица где содержится PE32 [R.3], который заполняет win32 загрузчик, когда модуль[R.4] загружен и также на дальнейшей загрузке, используя stub в IAT.
Внешние символы, в которых нуждается модуль, называются импортом, а символы, которые модуль предоставляет другим модулям, называются экспортом.
В IAT [R.3] модуля есть адрес его импорта, это значит, что в IAT [R.3] модуля есть адрес экспорта используемых из других модулей.
------[ 2.2.1 - Загрузка из Import Address Table
Для win32 загрузчика, который может получить экспорт, нужно узнать: модуль в котором он расположен, имя экспорта и/или ordinal [R.3].
В PE32 имеет структура IMAGE_IMPORT_DESCRIPTOR [R.5], где мы можем выделить 3 области:
Code:
- Name : Имя модуля где находится экспорт.
- OriginalFirstThunk : Адрес таблицы импорта
- FirstThunk : Адрес таблицы, идентичной OriginalFirstThunk,
куда win32 загрузчик помещает адреса импорта.
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
DWORD OriginalFirstThunk;
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
Каждая запись в таблице FirstThunk и OriginalFirstThunk имеет 2 поля[R.3]:
Code:
- Hint: если первые 31/63 bits составляют 0x80000000, то импорт будет
произведён по ordinal, в противном случаи нет.
Биты 15-0 это ordinal.
- Name: Адрес, где хранятся имена экспорта.
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;
------[ 2.3 - Запуск процесса в приостановленном состоянии
Когда мы хотим создать процесс в приостановленном состоянии, то нам необходимо знать, какого типа он [R.6]:Консольные тип процесса могут быть созданы с помощью API CreateProcess и флага CREATE_SUSPENDED.
Если GUI процесс открывается с флагом CREATE_SUSPENDED, то он может работать не корректно, поэтому он должен быть создан с помощью API:
Code:
1.- CreateProcess : Процесс создаётся без флага CREATE_SUSPENDED.
2.- WaitForInputIdle: Дождаться корректной загрузки [R.6] процесса.
3.- SuspendThread : Приостановить главный поток.
------[ 2.4 - Инъекция DLL в процесс
Существует много способов внедрения DLL в процесс [R.7], самый простой это использовать связку API:
Code:
1.- VirtualAllocEx : Зарезервировать память в процессе.
2.- WriteProcessMemory: Записать в зарезервированное место код
который загрузит DLL.
3.- CreateRemoteThread: Создать поток в процессе каторый выполнит
записанный код.
4.- VirtualFreeEx : Освободить зарезервированную память после
подгрузки DLL.
------[ 2.5 - Hooks в ring3
Всегда существует куча форм для реализации перехвата в win32 как в ринг0 так и в ринг3. Проблема при работе в ring0 заключается в том, что если код работает не стабильно, то это отразиться на всей ОС. Самый стабильный метод для OS реализовать перехват из ring3.
Самые известные методы:- IAT HOOKING: Запись IAT [R.3] изменяется, так чтоб загрузчик win32, указывал на другую область [R.8].
- PUSH + RET: В область кода PUSH DIRECTION и RET вставляется jump, чтоб передать управление своему коду, но приходится восстанавливать оригинальный код в определённый момент [R.9].
- SetWindowHook...: С помощью этих API, вызов своего кода может быть зарегистрирован для различных событий в системе.
------[ 2.5.1 - Проблемы
Некоторые проблемы при реализации перехвата в ring3:
Code:
+-------------------------------------------------------------------------+
| Метод | Проблема |
+------------------------+------------------------------------------------+
| IAT HOOKING [R.8] | 1.- IAT [R.3] для всех загружаемых модулей |
| | должен быть изменён. |
| | 2.- Модулю не нужен IAT [R.3] для |
| | использования символов экспортируемых |
| | другими. |
| | 3.- Это всем хорошо известно. |
| | 4.- Легко восстановить. |
| | 5.- Можно обнаружить. |
| | 6.- Не даёт полный контроль сразу после старта.|
|------------------------+------------------------------------------------|
| PUSH + RET [R.9] | 1.- Метод не универсален. |
| | 2.- Сложно в применении. |
| | 3.- Легко восстановить. |
| | 4.- Можно обнаружить. |
| | 5.- Не даёт полный контроль сразу после старта.|
|------------------------+------------------------------------------------|
| Otros "hooks": | 1.- Не даёт полного контроля. |
| SetWindowHook... [R.10]| 2.- Легко восстановить. |
| | 3.- Можно обнаружить. |
|------------------------+------------------------------------------------|
| PEB HOOKING [T.1] | 1.- Сложно в применении. |
| | 2.- Оригинальная DLL и внедрённая, должна |
| | экспортировать теже символы в том же |
| | объеме (как минимум). |
| | 3.- Можно обнаружить. |
| | 4.- Не даёт полный контроль сразу после старта.|
+------------------------+------------------------------------------------+
Примечание: Эта таблица только мнение авторов.
Вызовы из ring3 в ring0 используя SYSENTER не могут управляться только с помощью предыдущих методов. Системны вызов из ring3 могут быть реализованы SYSENTER [R.11] без каких либо других DLL, таких образом, предыдущие методы сделались непригодным для использования, это довольно редкая ситуация.
Из-за предыдущих проблем, мы решили использовать PEB HOOKING [T.1], чтобы создать механизм, который делает больше чем хук : phook - The PEB Hooker.
Примечание: Преимущества и недостатки PEB HOOKING [T.1] разъясняются в section 7.
------[ 3.- Разработка
В этом разделе будет говориться о базовой концепции и реализации PEB HOOKING [T.1]. Реализация не сложная, но только тогда, когда понимаешь для чего и зачем применяется тот или иной код.
Шаги:
- Загрузить DLL_FAKE и DLL_REAL.
- В списке, используемым загрузчиком вин32, в котором перечислены все загруженные в данный момент модули, нужно поменять поля между DLL_FAKE и DLL_REAL
- Необходимо чтобы IAT [R.3] всех загруженных модулей, кроме DLL_REAL и возможно DLL_FAKE указывали функциям, что DLL_FAKE экспорт.
------[ 3.1 - Первый шаг к PEB HOOKING
Прежде чем что-то сделать, необходимо загрузить DLL_FAKE в память процесса, к которому это требуется что-бы использовать PEB HOOKING [T.1]. DLL_FAKE должен иметь по крайней мере тот же самый экспорт что и DLL_REAL.
------[ 3.2 - Обмен данными в LoaderData
Необходимо найти в DLL_FAKE и DLL_REAL некоторые идентификаторы LDR_MODULE, после чего обменяться следующей информацией:- EntryPoint
- BaseAddress
- SizeOfImage (почти всегда)
Поиск с использованием поля BaseDllName будет получать данные о "LDR_MODULE", относящиеся к DLL_FAKE. Некоторые вирусы, упаковщики и API используют эту форму поиска, чтобы найти BaseAddress или EntryPoint для модуля.
Необходимо изменить поле SizeOfImage если DLL_FAKE и DLL_REAL, не имеют равный размера в памяти.
Поиск BaseAddress из kernel32.dll без "PEB HOOKING":
Code:
0 +---------------------------------+
[ process ] ---------+ | Process Environment Block (PEB) |
| |---------------------------------|
| | InheritedAddressSpace |
| | ReadImageFileExecOptions |
| | BeingDebugged |
| | Spare |
| | Mutant |
| | ImageBaseAddress |
+->| LoaderData |--+
| ... | |
+---------------------------------+ | 1
|
|
+--------------------------------------------------------------+
| +----------------------------+ +----------------------------+
| | LoaderData | | LDR_MODULE |
| +----------------------------+ |----------------------------| flink
| | Length | | InLoadOrderModList |-----+
| | Initialized | | InMemoryOrderModList | |
| | SsHandle | | InInitOrderModList | |
+->| InLoadOrderModList | 2 | ... | |
| InMemoryOrderModList |---->| BaseDllName "ntdll.dll" |---+ |
| InInitOrderModList - Flink | +----------------------------+ | |
+----------------------------+ +------------------------------------+ |
| +----------------------------+ |
| | LDR_MODULE (DLL_REAL) | |
| |----------------------------| |
| | InLoadOrderModList | 6 |
+---------------------+ 3 | | InMemoryOrderModList | |
| ¿Es "kernel32.dll"? |<-------+ | InInitOrderModList | |
+---------------------+ | BaseAddress 7C801000 | |
8 | |4 ^ 7 | ... | |
Si <-+ +-> No +-------------| BaseDllName "kernel32.dll" |<----+
| | 5 | ... |
9 | v +----------------------------+
| NextLdrModule();
v
kernel32.dll = 7C801000
Поиск BaseAddress из kernel32.dll с использованием PEB HOOKING [T.1]:
Code:
0 +---------------------------------+
[ process ] ---------+ | Process Environment Block (PEB) |
| |---------------------------------|
| | InheritedAddressSpace |
| | ReadImageFileExecOptions |
| | BeingDebugged |
| | Spare |
| | Mutant |
| | ImageBaseAddress |
+->| LoaderData |--+
| ... | |
+---------------------------------+ | 1
|
|
+--------------------------------------------------------------+
| +----------------------------+ +----------------------------+
| | LoaderData | | LDR_MODULE |
| +----------------------------+ |----------------------------| flink
| | Length | | InLoadOrderModList |-----+
| | Initialized | | InMemoryOrderModList | |
| | SsHandle | | InInitOrderModList | |
+->| InLoadOrderModList | 2 | ... | |
| InMemoryOrderModList |---->| BaseDllName "ntdll.dll" |---+ |
| InInitOrderModList - Flink | +----------------------------+ | |
+----------------------------+ +------------------------------------+ |
| +----------------------------+ |
| | LDR_MODULE (DLL_REAL) | |
| |----------------------------| 6 |
| | InLoadOrderModList | |
+---------------------+ 3 | | InMemoryOrderModList |flink|
| ¿Es "kernel32.dll"? |<-------+ | InInitOrderModList |--+ |
+---------------------+ | BaseAddress 7C801000 | | |
12 | |4-8 ^ ^ 7 | ... | | |
Si <-+ +-> No | +-------------| BaseDllName "old_k32.dll" |<-|--+
| 5-9 | +------------+ | ... | |
13 | v | +----------------------------+ |
| NextLdrModule(); +-+ |
v | +----------------------------+ |
kernel32.dll = 005C5000 | | LDR_MODULE (DLL_FAKE) | | 10
| |----------------------------| |
11 | | InLoadOrderModList | |
| | InMemoryOrderModList | |
| | InInitOrderModList | |
| | BaseAddress 005C5000 | |
| | ... | |
+-| BaseDllName "kernel32.dll" |<+
| ... |
+----------------------------+
Результаты поиска:- BaseAddress без использования PEB HOOKING [T.1]: 7C801000 (DLL_REAL)
- BaseAddress с использованием PEB HOOKING [T.1]: 005C5000 (DLL_FAKE)
PD: В поиске по InLoadOrderModList, первое поле показывает, что LDR_MODULE соответствует основному модулю. В примере он был опущен для ясности.
------[ 3.3 - Динамическая загрузка модулей
Кoгда процесс, PEB HOOKING [T.1] будет выполнен, динамически [R.12] загруженные модули будут иметь импорт DLL_REAL, его IAT [R.3] будет автоматически загружен с необходимым экспортом DLL_FAKE.
------[ 3.4 - Восстановление IAT
Кроме модулей DLL_FAKE и DLL_REAL, все IAT [R.3] экспортирующие DLL_REAL, должны быть заменены DLL_FAKE. IAT [R.3] DLL_FAKE не должен изменяться в случаи если DLL_REAL необходимо использовать.
Если IAT из DLL_FAKE модифицирована таким образом, что экспорты DLL_REAL совпадают с DLL_FAKE, вызов экспорта из DLL_REAL из такого же экспорта DLL_FAKE войдет в непрерывный бесконечный цикл, вызывающий переполнение стека.
Code:
+--------------------------+ +--------------------------------+
| .text DLL_FAKE | | IAT |
|--------------------------| |--------------------------------|
| ... | | LocalAlloc 1 (Nr_LocalAlloc) |
| PUSH EBP | +->| LoadLibrary 2 (Nr_LoadLibrary) |--+
| MOV EBP, ESP | | | .... | |
| ... | | +--------------------------------+ |
| LoadLibrary_FAKE: | | |
+->| PUSH original_lib_name | | 0 |
| | CALL IAT[Nr_LoadLibrary] |--+ |
| | ... | |
| | POP EBP | |
| | RET | |
| | ... | |
| +--------------------------+ |
| 1 |
+-----------------------------------------------------------------------+
Реальную проблему составляет то, что мы обращаемся сами к себе или одной из других DLL. Это не должно восстанавливать IAT [R.3] любого другова модуля (DLL_ANY), когда DLL_FAKE вызывает экспорт DLL_ANY который в свою очередь обращается к экспорту DLL_FAKE, который снова обращается к экспорту DLL_ANY.
Вызов RtlHeapAlloc, когда PEB HOOKING [T.1] выполнен через NTDLL.DLL и IAT kernel32.dll был изменён:
Пример:
Code:
[ proceso ]
|
| CALL RtlHeapAlloc CALL LoadLibrary
+-------------------> [DLL_FAKE ntdll.dll] ------------------+
0 ^ 1 |
| CALL RtlInitUnicodeString v
+--------------------------- [DLL_ANY kernel32.dll]
2
Вызов RtlHeapAlloc, когда PEB HOOKING [T.1] выполнен через NTDLL.DLL и IAT [R.3] kernel32.dll не был изменен:
Code:
[ proceso ]<----------------+
| 4 |
| CALL RtlHeapAlloc | CALL LoadLibrary
+-------------------> [ DLL_FAKE ntdll.dll] ------------------+
0 ^ 1 |
+------------------+ |
| 3 |
| CALL RtlInitUnicodeString v
[DLL_REAL old_nt.dll] <--------------------------- [DLL_ANY kernel32.dll]
2
Примечание: Схема была упрощенна, исключив другие вызовы DLL_FAKE.
Нормальный вызов LoadLibrary из процесса (без PEB HOOKING [T.1]):
Code:
CALL IAT[Nr_LoadLibrary] +--------------------------------+
[process] -------------------------+ | IAT |
^ 0 | |--------------------------------|
| | | LocalAlloc 1 (Nr_LocalAlloc) |
| +-----------------------+ +->| LoadLibrary 2 (Nr_LoadLibrary) |-+
| | DLL_REAL kernel32.dll | | .... | |
| |-----------------------| +--------------------------------+ |
| | ... | 1 |
| | LoadLibrary: | <--------------------------------------+
| 2 | PUSH EBP |
| | MOV EBP, ESP |
| | ... |
| | POP EBP |
+----| RET |
| ... |
+-----------------------+
Вызов проходит нормально без захода в DLL_REAL.
Вызов LoadLibrary в процессе с PEB HOOKING [T.1]:
Code:
CALL IAT[Nr_LoadLibrary] +--------------------------------+
[process] -------------------------+ | IAT |
^ 0 | |--------------------------------|
| | | LocalAlloc 1 (Nr_LocalAlloc) |
| +-------------------------+ +->| LoadLibrary 2 (Nr_LoadLibrary) |-+
| | DLL_FAKE kernel32.dll | | .... | |
| |-------------------------| +--------------------------------+ |
4 | | ... | 1 |
| | Own_LoadLibrary: | <--------------------------------------+
| | PUSH EBP |
| | MOV EBP, ESP | +-----------------------------+
| | // Own functions... | 2 | DLL_REAL old_k32.dll |
| | CALL IAT[Nr_LoadLibrary]|----+ |-----------------------------|
| | POP EBP |<-+ | | ... |
+--| RET | | +->| LoadLibrary: |
| ... | | | PUSH EBP |
+-------------------------+ | | MOV EBP, ESP |
| | ... |
3 | | POP EBP |
| | RET |--+
| | ... | |
| +-----------------------------+ |
+-------------------------------------+
Рассмотрев схему можно увидеть, что вызов проходит сначало через DLL_FAKE. Затем DLL_FAKE вызывает оригинальную LoadLibrary (DLL_REAL).
------[ 3.5 - Начало выполнения
Как только предыдущие шаги выполнены, настал момент для началa выполнения процесса и слежения за его работоспособностью.
------[ 3.6 - API для работы с модулями
API - LoadLibrary, GetModuleHandle, EnumProcessModules [R.12] ... используют поле LoaderData из PEB [T.1]. Это означает, что каждый раз, они вызывают что-то из DLL_REAL, которая вызывает что-то из DLL_FAKE, например:
Code:
PEB HOOKING [T.1] был выполнен для USER32.DLL:
- DLL_FAKE
- Name in memory: USER32.DLL
- BaseAddress: 00435622
- DLL_REAL
- Name in memory: OLD_U32.DLL
- BaseAddress: 77D10000
Процесс пытается получить базу USER32.DLL:
- HMODULE user32 = GetModuleHandle( "user32.dll" );
После выполнения GetModuleHandle [R.12] в переменной user32 будет: 00435622 (BaseAddress из DLL_FAKE). Если процесс выполнен позже GetProcAddress [R.12] на некоторые функции экспорта USER32.DLL, они получат функции из DLL_FAKE.
Блогадоря PEB HOOKING [T.1] больше нет необходимости изменять API, которые работают с модулями, так чтоб они использовали DLL_FAKE.
------[ 3.7 - Новая разработка: DLL MINIFILTER
DLL MINIFILTER это название, которые мы дали способности, вызывать экспорт проходя через несколько DLL_FAKE. Одной из самых важных особностей метода является, ограничение или расширение функциональных возможностей к запросу на экспорт.
Когда PEB HOOKING [T.1] выполнен с DLL_FAKE, то термин DLL_REAL для новых DLL_FAKE становится предыдущий DLL_FAKE. Поток пойдёт по форме последней DLL_FAKE, над которым взял контроль PEB HOOKING [T.1] по отношению к DLL_REAL, в случаи если все DLL_FAKEs приводят к оригинальному экспорту.
Поток запроса процесса, с PEB HOOKING [T.1], только с одним DLL_FAKE:
Code:
0 1
[proceso] --> [DLL_FAKE] --> [DLL_REAL]
^ |
| 2 |
+----------------------------+
Поток запроса процесса, с PEB HOOKING [T.1], с тремя DLL_FAKEs:
Code:
0 1 2 3
[proceso] --> [DLL_FAKE 3] --> [DLL_FAKE 2] --> [DLL_FAKE 1] --> [DLL_REAL]
^ |
| 4 |
+---------------------------------------------------------------+
В предыдущем примере все DLL_FAKEs получают контроль соответствующий DLL_REAL.
------[ 3.8 - Частые проблемы
На данный момент при реализации PEB HOOKING [T.1] выявлены, следующие проблемы:
Code:
+-------------------------------------------------------------------------+
| Проблема | Возможные решения |
|-------------------------------+-----------------------------------------|
| - PEB HOOKING [T.1] fails | - Проверьте, могут ли необходимые поля |
| | PEB [T.1] обмениваться. |
| | - Проверьте, есть ли доступ |
| | для изменения в IATs [R.3] |
|-------------------------------+-----------------------------------------|
| - Выполнение процесса не | - Проверьте корректность PEB [R.1] |
| происходит | - Проверьте значения IATs [R.3] |
| | модуля во всех процессах |
| | - Проверьте были ли восстановлены |
| | изменения в памяти PEB HOOKING [T.1] |
+-------------------------------------------------------------------------+
------[ 4.- phook
phook способен реализовать PEB HOOKING [T.1] (и кое что ещё). phook это проект из различных модулей:
- InjectorDLL: Создаёт приостановленный процесс и внедряет в него DLL.
- Console Control: Внедрённая DLL позволяет выполнит PEB HOOKING [T.1]. и другие задачи в интерактивном режиме посредством команд консоли через sockets.
- CreateExp: Программа создающая из DLL_REAL код, нужный для DLL_FAKE.
- ph_ker32.dll: DLL_FAKE из kernel32.dll. ph_ker32.dll смотрит за доступом к API: CreateFileA and CreateFileW [R.14].
------[ 4.1 - InjectorDLL
Программа создаёт приостановленный процесс и внедряет в него DLL. Для внедрения DLL C:\console.dll в процесс C:\poc.exe:
- - Тип процесса:
- - CONSOLE:
- - InjectorDLL.exe C:\console.dll -c C:\poc.exe
- - GUI:
- - InjectorDLL.exe C:\console.dll -g C:\poc.exe
- - Неизвестный тип:
- - InjectorDLL.exe C:\console.dll -u C:\poc.exe
InjectorDLL, с параметром -u, пытается обнаружить GUI или Console чтобы знать как создавать приостановленный поток (см пунтк 2.3). Этот метод создаёт процесс при помощи API CreateProcess и флага CREATE_SUSPENDED [R.6]. Потом вызывает WaitForInputIdle, если это не приносит результата то это консольный процесс, иначе GUI.
Code:
CreateProcess
(
program_name ,
NULL ,
NULL ,
NULL ,
FALSE ,
CREATE_SUSPENDED | CREATE_NEW_CONSOLE ,
NULL ,
NULL ,
pstart_inf ,
ppro_inf
)
// Необходимо проверить тип созданного процесса
if ( WaitForInputIdle( ppro_inf->hProcess, 0 ) == WAIT_FAILED )
// "Console процесс"
else
// "GUI процесс"
Если известен тип процесса мы знаем как его правельно остановить (см. пункт 2.3).
Примечание: метод не всегда работает, например если "Console процесс" будет опознан как "GUI процесс".
Код который загружает DLL помещён в структуру под названием LOADER_DLL_s (см. пункт 2.3). LOADER_DLL_s состоит из команд на ассемблере и всеми необходимыми данными. В созданном процессе необходимо описать структуру LOADER_DLL_s и объявить CreateRemoteThread, как точку запуска структуры. Она будет выполняться в коде LOADER_DLL_s.
Как только DLL загружена и поток приостановлен, LOADER_DLL_s начинает выполнение и устанавливает флаг для "опознания".
Code:
typedef struct LOADER_DLL_s
{
/* - CODE ------------------------------------------------------ */
PUSH_ASM_t push_name_dll; /* PUSH "DLL_INJECT.DLL"*/
CALL_ASM_t call_load_library; /* CALL LoadLibraryA */
CALL_ASM_t call_get_current_thread; /* CALL GetCurrentThread*/
INC_BYTE_MEM_t inc_flag; /* INC [FLAG] */
char PUSH_EAX; /* PUSH EAX */
CALL_ASM_t call_suspendthread; /* CALL SuspendThread */
/* - DATA ------------------------------------------------------ */
char name_dll[MAX_PATH]; /* DLL_INJECT.DLL'\0' */
char flag; /* [FLAG] */
} LOADER_DLL_t;
------[ 4.2 - Консоль управления
Консолью управления является DLL, которая внедрена в процессе, в котором вы хотели бы реализовать PEB HOOKING [T.1]. Это позволяет сделать PEB HOOKING [T.1] и другие задачи в интерактивном режиме с помощью команд консоли через sockets. Через прослушиваемый порт, в файл C:\ph_listen_ports.log записывается, PID - PORT. Например процесс с PID 2456, прослушивать на 1234 порт: 2456 - 1234.
На данный момент поддерживаются следующие команды:
Code:
help - Показать справку
exit - Закрыть и выгрузить консоль
suspend - Приостановить выполнение программы
resume - Возобновить выполнение программы
showmodules - Показать список модулей
load [param1] - Загрузить в память библиотеку указанную
в [param1]
unload [param1] - Выгрузить из памяти библиотеку указанную
в [param1]
pebhook [param1] [param2] - Реализовать PEB HOOKING [T.1] над dll
[param1]: Имя оригинальной dll
[param2]: путь до DLL_FAKE
Эти команды легки для понимания, но мы обьясним как работают "showmodules", "pebhook" и "suspend".
Команда "showmodules" выполняет поиск по PEB [R.1] из загружаемых модулей, без использования API.
pebhook которая реализовывает весь процесс PEB HOOKING (см. пункт 3).
Если требуется выполнить PEB HOOKING [T.1] для kernel32.dll , используйте DLL_FAKE "C:\phook\bin\windows_xp_sp2\ph_ker32.dll", для ОС Windows XP SP2, требуется только отправить команду:
- pebhook kernel32.dll c:\phook\bin\windows_xp_sp2\ph_ker32.dll
Команда "suspend" способна приостановить выполнение главного потока процесса. TID основного потока получен, просматривая THREADENTRY32 [R.13] этой системы, можно достигнуть первого из процесса:
Code:
BOOL GetMainThreadId( DWORD * thread_id )
{
HANDLE hThreadSnap;
THREADENTRY32 th32;
BOOL return_function;
DWORD process_id;
process_id = GetCurrentProcessId();
hThreadSnap = INVALID_HANDLE_VALUE;
return_function = FALSE;
hThreadSnap = \
CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, process_id );
if( hThreadSnap == INVALID_HANDLE_VALUE )
{
ShowGetLastErrorString
( " GetMainThreadId() - CreateToolhelp32Snapshot()" );
return FALSE;
}
th32.dwSize = sizeof( THREADENTRY32 );
if( !Thread32First( hThreadSnap, & th32 ) )
ShowGetLastErrorString( "GetMainThreadId() - Thread32First()");
do
{
if ( th32.th32OwnerProcessID == process_id )
{
* thread_id = th32.th32ThreadID;
return_function = TRUE;
}
}
while
(
Thread32Next( hThreadSnap, & th32 ) && return_function != TRUE
);
CloseHandle( hThreadSnap );
return return_function;
}
------[ 4.3 - CreateExp
CreateExp это программа создает исходный код, необходимый для реализации DLL_FAKE из a DLL_REAL. На данный момент она способна создавать .c и .def, для использования с mingw.
Для создания DLL_FAKE для kernel32.dll необходимо выполнить:
- CreateExp C:\WINDOWS\SYSTEM32\KERNEL32.DLL C:\ph_ker32
После успешного выполнения создадутся C:\ph_ker32.c и C:\ph_ker32.def.
ph_ker32.c содержит в себе экспорт из kernel32.dll и автоматически jumps для оригиналов.
ph_ker32.def содержит псевдонимы и имена из экспорта kernel32.dll.
По умолчанию экспорт из DLL_FAKE приведёт к экспорту из DLL_REAL.
------[ 4.3.1 - Forwarder DLL
CreateExp преобразовывает Forwarder DLL [R.3] в экспорт PEB HOOKING таким образом функция Forwarder может быть создана.
Пример: kernel32.dll имеет Forwarder HeapAlloc который идет в экспорте RtlAllocateHeap of NTDL.DLL. Когда модуль импортирует HeapAlloc из kernel32.dll, загрузчик win32 автоматически помещает адрес экспорта NTDLL.DLL и никогда не проходит через kernel32.dll:
Code:
CALL HeapAlloc
[proceso] ------------------> [NTDLL.DLL]
^ 0 |
+-------------------------------+
1
Если DLL_FAKE из kernel32.dll создается с CreateExp, то поток будет:
Code:
CALL HeapAlloc (DLL_FAKE)
[proceso] ------------------> [KERNEL32.DLL] --------> [NTDLL.DLL]
^ 0 1 |
+-----------------------------------------------------+
2
В такой форме мы можем осуществить хук HeapAlloc (kernel32.dll).
------[ 4.4 - ph_ker32.dll
ph_ker32.dll была создана для реализации PEB HOOKING [T.1] из kernel32.dll; Наблюдает за APIs "CreateFileA" и "CreateFileW" [R.14], и когда их вызывают, их ( или любые другие ) перенаправляют на оригинальные.
Чтобы ослаблять прыжок к API, бал создан макрос JMP, он должно передать название DLL и оригинальный экспорт (см. пункт 4.4.2).
ph_ker32.c созданный с CreateExp (JMP макрос был пропущен):
Code:
#define FAKE_LIB "ph_ker32.dll"
DLLEXPORT void _ActivateActCtx ( void )
{
JMP( FAKE_LIB, 1 );
}
DLLEXPORT void _AddAtomA ( void )
{
JMP( FAKE_LIB, 2 );
}
DLLEXPORT void _AddAtomW ( void )
{
JMP( FAKE_LIB, 3 );
}
DLLEXPORT void _AddConsoleAliasA ( void )
{
JMP( FAKE_LIB, 4 );
}
....
Необходимо помнить, что после выполнения PEB HOOKING [T.1], kernel32.dll будет называться ph_ker32.dll, поэтому ph_ker32.dll обозначен как константа FAKE_LIB.
ph_ker32.def созданный с CreateExp:
Code:
LIBRARY default
EXPORTS
ActivateActCtx=_ActivateActCtx @ 1
AddAtomA=_AddAtomA @ 2
AddAtomW=_AddAtomW @ 3
...
Причинами ясности выполнение APIs CreateFileA и CreateFileW [R.14] были помещены в файл owns.c. Когда сделан запрос к CreateFileA, и к CreateFileW [R.14] то записывается параметр lpFileName в файле C:\CreateFile.log
Code:
owns.c:
#define FILE_LOG C:\CreateFile.log
DLLEXPORT
HANDLE _stdcall _CreateFileW
(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
{
char asc_str[MAX_PATH];
if ( UnicodeToANSI( (WCHAR *) lpFileName, asc_str ) == 0 )
CreateFileLogger( asc_str );
return CreateFileW(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDistribution,
dwFlagsAndAttributes,
hTemplateFile );
}
DLLEXPORT
HANDLE _stdcall _CreateFileA
(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
{
char asc_str[MAX_PATH];
CreateFileLogger( lpFileName );
return CreateFileA(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDistribution,
dwFlagsAndAttributes,
hTemplateFile );
}
static void
CreateFileLogger( const char * file_to_log )
{
HANDLE file;
DWORD chars;
file = \
CreateFileA
(
FILE_LOG ,
GENERIC_WRITE | GENERIC_READ ,
0 ,
NULL ,
OPEN_ALWAYS ,
0 ,
NULL
);
if ( file != INVALID_HANDLE_VALUE )
{
if ( SetFilePointer( file, 0, NULL, FILE_END ) != -1 )
{
WriteFile
(
file, file_to_log, strlen( file_to_log ), &chars, NULL
);
WriteFile( file, "\x0D\x0A", 2, &chars, NULL );
}
CloseHandle( file );
}
}
------[ 4.4.1 - Проблемы стэка
Когда требуется непосредственно передать контроль к API, необходимо передать его неповрежденный стек оригиналу API. Нужно в mingw выбрать compilator-fomit-frame-pointer [R.15] и JMP (ASM) к оригиналу API.
Функции, которые были осуществлены, должны быть помещены образец и должны иметь тип _stdcall. Функции типа _stdcall имеют различный синтаксис в файле .def:
- Name_exportation=Alias@arguments * 4 @ Ordinal
Пример файла .def с APIs типа _stdcall CreateFileA и CreateFileW [R.14] (оба имеют семь аргументов):
Code:
LIBRARY ph_ker32
EXPORTS
; Name Exp | Alias | No Args * 4 | Ordinal Windows XP SP2
CreateFileW=_CreateFileW@28 @ 83
CreateFileA=_CreateFileA@28 @ 80
Функции типа _stdcall не должны быть скомпилированы с опцией с-fomit-frame-pointer [R.15].
------[ 4.4.2 - Проблемы регистра
Не только необходимо передать стек с неповреждённым экспортом, экспортирование должно быть с целостностью регистраторов. Перед прохождением контроля к оригинальному экспортированию, необходимо чтобы регистры не были повреждены, это достигается использованием в коде инструкции PUSHAD и POPAD:
- [PUSHAD] [ CODE NEEDED TO JUMP TO THE EXPORTATION ] [POPAD]
Пример экспортирования с использованием регистров _chkstk в NTDLL.DLL:
Code:
_chkstk in NTDLL.DLL (WINDOWS XP SP2):
7C911A09 >/$ 3D 00100000 CMP EAX,1000
7C911A0E |. 73 0E JNB SHORT ntdll.7C911A1E
7C911A10 |. F7D8 NEG EAX
7C911A12 |. 03C4 ADD EAX,ESP
7C911A14 |. 83C0 04 ADD EAX,4
7C911A17 |. 8500 TEST DWORD PTR DS:[EAX],EAX
7C911A19 |. 94 XCHG EAX,ESP
7C911A1A |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
7C911A1C |. 50 PUSH EAX
7C911A1D |. C3 RETN
7C911A1E |> 51 PUSH ECX
7C911A1F |. 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8]
7C911A23 |> 81E9 00100000 /SUB ECX,1000
7C911A29 |. 2D 00100000 |SUB EAX,1000
7C911A2E |. 8501 |TEST DWORD PTR DS:[ECX],EAX
7C911A30 |. 3D 00100000 |CMP EAX,1000
7C911A35 |.^73 EC \JNB SHORT ntdll.7C911A23
7C911A37 |. 2BC8 SUB ECX,EAX
7C911A39 |. 8BC4 MOV EAX,ESP
7C911A3B |. 8501 TEST DWORD PTR DS:[ECX],EAX
7C911A3D |. 8BE1 MOV ESP,ECX
7C911A3F |. 8B08 MOV ECX,DWORD PTR DS:[EAX]
7C911A41 |. 8B40 04 MOV EAX,DWORD PTR DS:[EAX+4]
7C911A44 |. 50 PUSH EAX
7C911A45 \. C3 RETN
------[ 4.4.3 - JMP макрос
Макрос JMP необходим так, как не всегда весь DLL (файл .h) имеются в его header'e. С макросом JMP адрес экспорта получается с GetProcAddress [R.12] во времени выполнения.
Code:
unsigned long tmp;
#define JMP( lib, func ) \
asm ( "pushad" ); \
asm \
( \
" push edx \n" \
" push %1 \n" \
" call eax \n" \
" pop edx \n" \
" push %2 \n" \
" push eax \n" \
" call edx \n" \
" mov %4, eax \n" \
" popad \n" \
\
: : \
"a" (GetModuleHandle) , \
"g" (lib) , \
"g" (func) , \
"d" (GetProcAddress) , \
"g" (tmp) \
); \
asm ( "jmp %0" : : "g" (tmp) );
Это код для mingw [R.16], компилировать с опцией -masm=intel.
------[ 4.4.4 - Версии
Мы включили в phook различные версии ph_ker32 для систем:
Code:
- Windows XP SP2 v5.1.2600
- Windows Server 2003 R2 v5.2.3790
- Windows Vista v6.0.6000
Исходный код в ph_ker32/SO и бинарники в bin/OS.
------[ 4.5 - Использование phook
Далее рассмотрено что можно делать с PEB HOOKING [T.1] для kernel32.dll к ph_ker32.dll, программа poc.exe была выбрана для примера (лежит в папке bin\ of phook).
Шаги для следования:
1.- Запустите InjectorDLL с указанием программы для инжекта DLL, для для этого введите в консоли:
- InjectorDLL.exe console.dll -u poc.exe
Процесс будет в приостановленном виде и будет возможность для прослушки порта, записанном в файле C:\ph_listen_ports.log
Code:
C:\phook\bin>InjectorDll.exe console.dll -u poc.exe
________________________________________________________________
| InjectorDLL v1.0 |
| |
| Juan Carlos Montes eunimedes@hotmail.com |
| David Reguera Garcia Dreg@fr33project.org / Dreg@7a69ezine.org |
| -------------------------------------------------------------- |
| http://www.fr33project.org |
|________________________________________________________________|
Showing injection data .....
Program to inject : poc.exe
Library to inject: console.dll
[OK] - CONSOLE.
[OK] - Create process:
[INFO] PID: 0x0960
[INFO] P. HANDLE: 0x000007B8
[INFO] TID: 0x0AE0
[INFO] T. HANDLE: 0x000007B0
[INFO] - Injecting DLL...
[OK] - Allocate memory in the extern process.
[INFO] - Address reserved on the other process: 0x00240000
[INFO] - Space requested: 306
[OK] - Creating structure for the dll load.
[OK] - Writing structure for the dll load.
[OK] - Creating remote thread.
[INFO] - Thread created with TID: 0x0B28
[INFO] - Attempt: 1
[INFO] - Thread has entered suspension mode.
[OK] - Injection thread ended.
[OK] - Memory in remote thread freed.
[OK] - DLL injected.
[OK] - Injection ended.
2.- Необходимо соединиться с клиентом через netcat к открытому порту, в нашем случаи: 1234.
Code:
C:\>nc 127.0.0.1 1234
________________________________________________________________
| Phook Prompt v1.0 |
| Juan Carlos Montes eunimedes@hotmail.com |
| David Reguera Garcia Dreg@fr33project.org / Dreg@7a69ezine.org |
| -------------------------------------------------------------- |
| http://www.fr33project.org |
|________________________________________________________________|
ph > help
_________________________________________________________________
| Phook Prompt v1.0 |
| |
| Command list: |
| --------------------------------------------------------------- |
| help - Shows this screen |
| exit - Closes and unloads the console |
| suspend - Pauses the programs execution |
| resume - Resumes the programs execution |
| showmodules - Shows the modules list |
| load [param1] - Loads in memory the library |
| especified in [param1] |
| unload [param1] - Unloads a librery in memory |
| especified in [param1] |
| pebhook [param1] [param2] - Performs PEB Hook over a dll |
| [param1]: Name of the original dll |
| [param2]: Path to the DLL hook |
|_________________________________________________________________|
3.- PEB HOOKING [T.1] для kernel32.dll осуществляется с ph_ker32.dll:
Code:
ph > pebhook kernel32.dll C:\phook\bin\windows_xp_sp2\ph_ker32.dll
4.- Команда resume продолжает выполнение процесса.
Code:
ph > resume
ph >
C:\phook\bin>
5.- poc.exe creates the files in C:\
Code:
- file
- file2
- file3
6.- ph_ker32.dll регистрирует успешные API вызовы CreateFileA и CreateFileW [R.14] в файле C:\CreateFile.log
7.- C:\>more CreateFile.log
Code:
C:\file1
C:\file2
C:\file3
------[ 4.5.1 - DLL MINIFILTER
phook позволяет также реализовать и DLL MINIFILTER (см. пункт 3.7). Он только должен выполнить PEB HOOKING [T.1], с помощью команды pebhook, с необходимым именем DLL_FAKE, тоесть той что была DLL_REAL.
Предположим что у нас есть две DLL_FAKE:
- ph_ker32_1.dll: Следит за доступом к API CreateFile [R.14].
- ph_ker32_2.dll: Следит за доступом к API ReadFile [R.17].
Выполнения DLL MINIFILTER очень просто:
Code:
C:\>nc 127.0.0.1 1234
________________________________________________________________
| Phook Prompt v1.0 |
| Juan Carlos Montes eunimedes@hotmail.com |
| David Reguera Garcia Dreg@fr33project.org / Dreg@7a69ezine.org |
| -------------------------------------------------------------- |
| http://www.fr33project.org |
|________________________________________________________________|
ph > pebhook kernel32.dll C:\phook\bin\windows_xp_sp2\ph_ker32_1.dll
ph > pebhook kernel32.dll C:\phook\bin\windows_xp_sp2\ph_ker32_2.dll
Поступает вызов от процесса к kernel32.dll:
Code:
0 1 2
[proceso] --> [ph_ker32_2.dll] --> [ph_ker32_2.dll] -> [kernel32.dll]
^ |
| 3 |
+------------------------------------------------------+
------[ 4.6 - Частые проблемы
Помимо проблем описанных в section 3.8, есть и другие:
Code:
+------------------------------------------------------------------------+
| Problem | Possible/s Solution/s |
|------------------------------+-----------------------------------------|
| - DLL_FAKE ошибка компиляции | - Проверьте, что функции, которые |
| | выходят непосредственно на DLL_REAL |
| | не повторялись, и реализуются. |
| | - Проверьте, что выполнены функций |
| | (которые должны быть _stdcall типа) |
| | хорошо определено в .def файле |
| | (см. пункт 4.4.1). |
|------------------------------+-----------------------------------------|
| - Выполнение процесса | - Проверьте, что функции, которые |
| не происходит | выходят непосредственно на DLL_REAL |
| | были составлены с помощью опции |
| | -fomit-frame-pointer (см. пункт |
| | 4.4.1). |
| | - Проверьте, что выполнены функции |
| | имеют _stdcall типа. |
| | - Проверьте, что DLL_FAKE были созданы |
| | от DLL_REAL, а не от другой. |
| | - Проверьте, если InjectorDLL правильно |
| | обнаружен реальный тип процесса |
| | (GUI или CONSOLE). |
|------------------------------+-----------------------------------------|
| - Не удалось подключиться | - Проверьте что порт 1234 открыт |
| к консоли | перед вызовом PEB HOOKING [T.1]. |
| | - Проверьте что фаервол не блокирует... |
| | - Убедитесь в том, что полный путь |
| | console.dll было указано |
| | в InjectorDLL. |
|------------------------------+-----------------------------------------|
| - InjectorDLL не работает | - Проверьте что есть привилегии для |
| | внедрения DLL (CreateRemoteThread..) |
| | |
| | - Проверьте не блокирует ли антивирус.. |
|------------------------------+-----------------------------------------|
| - CreateExp не работает |- Проверьте DLL_REAL на правильность |
| | PE32 и EXPORT DIRECTORY [R.3]. |
+------------------------------------------------------------------------+
Некоторые другие проблемы могут возникнуть из-за проектирования или других несвязанных с phook ошибок программиста.
------[ 5.- Что делаем
На данный момент мы работаем над:- - Реализацией PEB HOOKING [T.1] до выполнения:
- TLS Table и DLLMain [R.3].
- Создать отладочные файлы конфигурации и для консоли.
- Правила для восстановления IATs [R.4].
- Список прослушивающих портов.
- ...
- - Улучшить InjectorDLL:
- Автоматическое распознавание "GUI процессов" и "Console процессов".
------[ 6.- Тестирование
Тестирование phook было произведено в различных версиях Windows и программах.
Code:
Windows:
- Windows XP SP2 v5.1.2600
- Windows Server 2003 R2 v5.2.3790
- Windows Vista v6.0.6000
Теоретически должно работать и в Windows 2000, но мы не можем подтвердить это.
Code:
Программы:
- Microsoft Word 10.0.2627.0
- Regedit 5.1.2600.2180
- Notepad 5.1.2600.2180
- Calc 5.1.2600.0
- CMD 5.1.2600.2180
- piathook 1.4
- pebtry Beta 5
- pe32analyzer Beta 2
------[ 7.- Преимущества и возможности
Главное преимущества PEB HOOKING перед другими в том что, он применяется только 1 раз.К моменту когда выполнен хук длл, любой загружаемый модуль автоматически получает в своей IAT экспорт DLL_FAKE. Остальные модули должны применять хук каждый раз когда модуль загружается.
Другие преимущества PEB HOOKING [T.1]:
- Поиск PEB (используя BaseDllName) чтоб найти DLL_REAL, будет находится в DLL_FAKE.
- PEB HOOKING является более стабильным для ОС чем использование ring0.
- Некоторые упаковщики не обнаруживают PEB HOOKING [T.1] так как это не документированный способ.
- Нет необходимости менять поведение работы API с модулями. Когда модуль обращается к DLL_REAL, то он автоматически обращается к DLL_FAKE.
- Возможность реализовать DLL MINIFILTER (см. пункт 3.7).
- PEB HOOKING может экспортировать Forwarder [R.3] не делая PEB HOOKING к Forwarder DLL.
Спектр возможностей PEB HOOKING [T.1] и phook достаточно большой, вот несколько примеров применения:
Code:
- Мониторинг/виртуализация доступа процесса к реестру:
- POC [R.18]:
1.- Запустите CreateExp (см. пункт 4.3) с
"advapi32.dll".
2.- Взависимости от того, что вы хотите сделать необходимо
наблюдать/виртуализовать следующие API:
- RegCloseKey
- RegCreateKeyA/RegCreateKeyW
- RegCreateKeyExA/RegCreateKeyExW
- RegDeleteKeyA/RegDeleteKeyW
- RegLoadKeyA/RegLoadKeyW
- RegOpenKeyA/RegOpenKeyW
- RegOpenKeyExA/RegOpenKeyExW
- RegQueryValueA/RegQueryValueW
- RegQueryValueExA/RegQueryValueExW
- RegReplaceKeyA/RegReplaceKeyW
- RegRestoreKeyA/RegRestoreKeyW
- RegSaveKeyA/RegSaveKeyW
- RegSaveKeyExA/RegSaveKeyExW
- RegSetValueA/RegSetValueW
- RegSetValueExA/RegSetValueExW
- RegUnLoadKeyA/RegUnLoadKeyW
...
- Наблюдение/виртуализация подключений.
- POC [R.20]:
1.- Запустите CreateExp (см. пункт 4.3) с "ws2_32.dll".
2.- Взависимости от того, что вы хотите сделать необходимо наблюдать/виртуализовать следующие API:
- accept
- bind
- closesocket
- connect
- listen
- recv
- recvfrom
- send
- sendto
- socket
- WSAAccept
- WSAConnect
- WSARecv
- WSARecvFrom
- WSASend
- WSASendTo
- WSASocketA/W
...
- Syscall Proxy of files:
- POC [R.19]:
1.- Запустите CreateExp (см. пункт 4.3) с "kernel32.dll".
2.- Взависимоти от того, что вы хотите сделать необходимо перенаправлять следующие API:
- CreateFileA/CreateFileW
- CreateFileExA/CreateFileExW
- ReadFile
- ReadFileEx
- WriteFile
- WriteFileEx
...
- ... и конечно ваши идеи ;-)
------[ 8.- Заключение
Если необходимо выполнить hook на API/экспорта, можно использовать любые методы. Но если необходимо наблюдать или виртуализировать доступ к различным API/экспорту, то с phook это намного проще осуществить.
Кроме того, это - метод, ориентируемый к обратному проектированию программного обеспечения и malware систем защиты, это как альтернативные методы поиска экспорта и устранения хуков.
------[ 9.- Благодарности
Recommendations for the paper:
Translation to English of the chains of phook:
Translations of the paper to English:- BETA : Ana Hijosa
- BETA 2: delcoyote
- ACTUAL: LogicMan
Virii scene:- GriYo, zert, Slow, pluf, xezaw, sha0 ...
Reversing scene:- pOpE, JKD, ilo, Ripe, int27h, at4r, uri, numitor, vikt0ry, kania, remains, S-P-A-R-K ...
Other scene:- sync, ryden, xenmax, ozone/membrive, \^snake^\, topo, fixgrain, ia64, overdrive, success, scorpionn, oyzzo, simkin, !dSR ...
ALL vx.7a69ezine.org and 7a69ezine.org people 
And specially thanks to YJesus - http://www.security-projects.com
------[ 10.- Похожие работы
- [T.1] .- Нам неизвестно о каких-то других работах с использованием phook, но есть статья с упоминанием PEB HOOKING написанная Deroko: "PEB DLL Hooking Novel method to Hook DLLs". Статья была опубликованна в ARTeam-Ezine выпуск 2.
------[ 11.- Ссылки
------[ 12.- Исходный код
Download "Source Code phook"
Izg0y © CORU, r0 Crew