Подмена CreateFile и ReadFile
От: Adnako СССР  
Дата: 30.12.13 12:57
Оценка:
Здравствуйте.

Задача в общих чертах такая — существует некий процесс который подгружает мою dll, необходимо перехватить обращения только этого процесса (и всех его загруженных модулей, кроме моего) к определённым файлам, чтобы "на лету" подменять содержимое читаемых процессом данных.

Изучая гугл пришёл к выводу, что писАть свой драйвер-фильтр будет "немножко" overkill, и остановился на методе модификации IAT. Возможно это не самый правильный способ, просто я пока не нашёл ещё других.
За основу был взят этот алгоритм "прочёсывания" всех IAT процесса и его модулей.

Теперь, собственно, проблема.
После получения структуры IMAGE_THUNK_DATA у меня все параметры имеют одинаковое значение, например:
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE) hMods[i] + pImportDesc->FirstThunk);
pThunk.u1 =
  ForwarderString  2147483665  unsigned long
  Function         2147483665  unsigned long
  Ordinal          2147483665  unsigned long
  AddressOfData    2147483665  unsigned long

Соответственно при попытке прочитать структуру IMAGE_IMPORT_BY_NAME:
PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)((DWORD)hMods[i] + pOriginalThunk->u1.AddressOfData);

В import лежит мусор.
Почти та же петрушка, если получать IMAGE_THUNK_DATA не по смещению FirstThunk, а по OriginalFirstThunk. Вся разница лишь в том, что значения смещений FirstThunk и OriginalFirstThunk разные и по итогу в import лежит немного другой мусор.

На SO есть похожий неудачник, но он более счастливый — он сам контролирует запускаемый процесс и мусор у него, потому, что процесс запущен с флагом CREATE_SUSPENDED, что в моём случае вообще безынтересно.
Я, конечно, попробовал — в моём случае после некоего таймаута, после загрузки моей dll, мусор лежит уже по смещению pImportDesc->FirstThunk, а попытка получить IMAGE_IMPORT_BY_NAME по смещению из OriginalFirstThunk приводит к результатам, что были ранее.

Небольшое уточнение — я всё это пытаюсь запустить из под Visual Studio 2008 на Windows 7 SP1 x64 в режиме Win32.

Неделя копания в гугле, компиляция кучи примеров не принесли положительных результатов — в результате у всех примеров лежит мусор в структуре IMAGE_IMPORT_BY_NAME.

Помогите, пожалуйста с советом — куда копать?
Актуальна ли на существующий день методология модификации IAT?
Есть ли какие-либо современные варианты перехвата WinAPI?

PS Все умные статьи, на подобие этой я уже перечитал. Возможно не всё понял, но материал достаточно обширен и времени погружаться в ассемблер нету. Может быть кто-то уже реализовывал подобные задачи и хотя бы посоветует какую статью изучить внимательнее, чтобы добиться положительного результата.

Спасибо.
Re: Подмена CreateFile и ReadFile
От: Danchik Украина  
Дата: 30.12.13 15:43
Оценка:
Здравствуйте, Adnako, Вы писали:

[Skip]

Может это?
http://research.microsoft.com/en-us/projects/detours/
Там есть express edition
Re: Подмена CreateFile и ReadFile
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.12.13 16:14
Оценка:
Здравствуйте, Adnako, Вы писали:

Как-то уже давно делал подобное.
Как тут уже советовали, есть МС детурс, но я тогда о нем не знал, поэтому делал на коленке сам. К слову, я потом глянул этот детурс, но так как нужда уже ушла, то не напрягался с изучением, и ниасилил

У меня задача была — пропатчить чужой экзешник. Я запускал exe, который нужно было пропатчить, в "замороженном" состоянии, инжектил в него dll, в которой были хакнутые версии функций, запускал процедуру хака, и запускал замороженный процесс.

Не совсем понял, что ты там делал (давно такими вещами уже не баловался), но вроде как-то сложно. Я просто дизасмил пролог функции из kernel32, копировал начальные инструкции, прописывал туда переход на свою функцию, делал там что надо, потом jump на скопированный код, после которого прописан jump на продолжение функции в kernel32. Вроде как-то так, но уже точно не помню.

PS тоже перехватывал файловые функции, расширял набор поддерживаемых форматов файлов для чужой прилады — на лету преобразовывал формат в понятный программе.

Во первых, см. сюда
Автор: Marty
Дата: 16.10.09
.

Использовать как-то так:


void * originalFindNextFileW = 0;

__declspec( naked )
BOOL WINAPI hackedFindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData)
   {
    __asm push ebp  
    __asm mov  ebp,esp 

    std::cout<<"FindNextFileW handler\n";

    __asm pop  ebp

    __asm jmp originalFindNextFileW
   }

...


    HMODULE hKernelDll = ::GetModuleHandleA( "kernel32.dll" );
    CODE_PTR orgFindNextFileW = (CODE_PTR)::GetProcAddress( hKernelDll, "FindNextFileW" );
    if (!orgFindNextFileW)
       {
        ::std::cout<<"Failed to get address of FindNextFileW\n";
        return 0;
       }

    result = installPatch( orgFindNextFileW, (CODE_PTR)hackedFindNextFileW /* absolute */, (ADDR32_T*)&originalFindNextFileW);
    ::std::cout<<"installPatch returns "<<(int)result<<" ("<<getECheckHotPatchResultStr(result)<<"\n";
    if ((int)result <0 )
       {
        ::std::cout<<"Failed to install patch\n";
        return 0;       
       }
    else
       {
        ::std::cout<<"FindNextFileW patch installed\n";
       }


    // Try to call FindNextFileW
    WIN32_FIND_DATAW fndData;
    //BOOL bRes = FindNextFileW( (HANDLE)0x00263368, &fndData);
    BOOL bRes = FindNextFileW( INVALID_HANDLE_VALUE, &fndData);

    WIN32_FIND_DATAA fndDataA;
    //BOOL 
    bRes = FindNextFileA( INVALID_HANDLE_VALUE, &fndDataA);





A>Спасибо.
Маньяк Робокряк колесит по городу
Re[2]: Подмена CreateFile и ReadFile
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.12.13 16:16
Оценка:
Здравствуйте, Marty, Вы писали:

А, в той же ветке первое сообщение — с примером — http://www.rsdn.ru/forum/src/3571389.1
Автор: Marty
Дата: 16.10.09
Маньяк Робокряк колесит по городу
Re[2]: Подмена CreateFile и ReadFile
От: Adnako СССР  
Дата: 30.12.13 21:51
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Adnako, Вы писали:


D>[Skip]


D>Может это?

D>http://research.microsoft.com/en-us/projects/detours/
D>Там есть express edition

Спасибо.
Забыл уточнить — я в курсе про детоурс, он платный и в моём случае это более чем из пушки по воробьям.
Ещё есть опенсорс аналог EasyHook, который отложен на свосем чёрный день.

Понимаете, проблема всех этих обёрток — скрыть реализацию и предоставить универсальный доступ ко всем возможностям обёртки.
Мне не нужна вся их мощь. Мне нужна простая подмена адреса в таблице. Это не rocket-science.

Беда в том, что по всему интернету моя задача представляется в совокупности с другой — инжектировать библиотеку в "чужой" процесс. И последней задаче уделено гораздо бОльшее внимание, а на получение IAT — две строчки считается явным перебором. И самое странное — похоже, что у них то всё работает или работало ранее.
Re[2]: Подмена CreateFile и ReadFile
От: Adnako СССР  
Дата: 30.12.13 21:55
Оценка:
Здравствуйте, Marty, Вы писали:

M>Не совсем понял, что ты там делал (давно такими вещами уже не баловался), но вроде как-то сложно. Я просто дизасмил пролог функции из kernel32, копировал начальные инструкции, прописывал туда переход на свою функцию, делал там что надо, потом jump на скопированный код, после которого прописан jump на продолжение функции в kernel32. Вроде как-то так, но уже точно не помню.


это известный и не совсем чистый путь
у меня ситуация с инжектом попроще — нет нужды в перетирании первых пяти байтов на джамп в свой метод, ибо у меня есть легальная возможность, появившись в потрохах процесса изменить его таблицу импорта только там где надо мне, вроде как

M>PS тоже перехватывал файловые функции, расширял набор поддерживаемых форматов файлов для чужой прилады — на лету преобразовывал формат в понятный программе.


M>Во первых, см. сюда
Автор: Marty
Дата: 16.10.09
.


M>Использовать как-то так:


Спасибо, изучим!
Re[3]: Подмена CreateFile и ReadFile
От: Adnako СССР  
Дата: 30.12.13 22:09
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, Marty, Вы писали:


M>А, в той же ветке первое сообщение — с примером — http://www.rsdn.ru/forum/src/3571389.1
Автор: Marty
Дата: 16.10.09


Любопытно, конечно.
Жаль, что за скобками осталась реализация installPatch, я так полагаю там происходит затирание первых байтов перехватываемого метода джампом на хакнутый метод.
К сожалению никто не гарантирует, что в будущем начало winapi-методов не изменится. Хочется так же понять — существует ли более универсальное решение, как например модификация IAT, или это такой же толщины костыль?
Re[4]: Подмена CreateFile и ReadFile
От: ononim  
Дата: 30.12.13 22:23
Оценка:
A>Любопытно, конечно.
A>Жаль, что за скобками осталась реализация installPatch, я так полагаю там происходит затирание первых байтов перехватываемого метода джампом на хакнутый метод.
A>К сожалению никто не гарантирует, что в будущем начало winapi-методов не изменится. Хочется так же понять — существует ли более универсальное решение, как например модификация IAT, или это такой же толщины костыль?
Я даже больше скажу — эти недохуки, рассчитывающие на определенный код пролога функции в N байтов или же патчащие/анпатчащие ее в рантайме дико мешают жить остальным, которые юзают detour-style хуки
Как много веселых ребят, и все делают велосипед...
Re[4]: Подмена CreateFile и ReadFile
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 31.12.13 04:19
Оценка:
Здравствуйте, Adnako, Вы писали:

A>Любопытно, конечно.

A>Жаль, что за скобками осталась реализация installPatch, я так полагаю там происходит затирание первых байтов перехватываемого метода джампом на хакнутый метод.

А ты http://www.rsdn.ru/forum/src/3571390.1
Автор: Marty
Дата: 16.10.09
таки внимательно смотрел? Есть там все.

A>К сожалению никто не гарантирует, что в будущем начало winapi-методов не изменится. Хочется так же понять — существует ли более универсальное решение, как например модификация IAT, или это такой же толщины костыль?


Изменится, и что? Все точно так же будет работать. Начало функции копируется не абы как, копируются несколько первых инструкций так, чтобы на их место влез переход на патченую версию
Маньяк Робокряк колесит по городу
Re[5]: Подмена CreateFile и ReadFile
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 31.12.13 04:21
Оценка:
Здравствуйте, ononim, Вы писали:

O>Я даже больше скажу — эти недохуки, рассчитывающие на определенный код пролога функции в N байтов или же патчащие/анпатчащие ее в рантайме дико мешают жить остальным, которые юзают detour-style хуки


Недохуки? А там зря что-ли дизассемблер прикручен, который декодирует инструкции и выбирает их количество так, чтобы влез патч?
На W2k, WinXP, Win7 все работало, за линейку 9x не помню, но думаю, что там все тоже ок.
Маньяк Робокряк колесит по городу
Re[5]: Подмена CreateFile и ReadFile
От: Kubyshev Andrey  
Дата: 31.12.13 07:59
Оценка:
O>Я даже больше скажу — эти недохуки, рассчитывающие на определенный код пролога функции в N байтов или же патчащие/анпатчащие ее в рантайме дико мешают жить остальным, которые юзают detour-style хуки

А что за детур-стайл ? Он что, по другому работает?
Re[6]: Подмена CreateFile и ReadFile
От: ononim  
Дата: 31.12.13 16:08
Оценка: 8 (1)
M>Недохуки? А там зря что-ли дизассемблер прикручен, который декодирует инструкции и выбирает их количество так, чтобы влез патч?
M>На W2k, WinXP, Win7 все работало, за линейку 9x не помню, но думаю, что там все тоже ок.
А зачем тогда у вас в коде асм какой-то?
В нормальных хуках никакие прологи хардкодить не надо. А надо
1) Как вы правильно сделали — декодировать N инструкций, длины которых хватает чтобы всунуть jmp
2) _Переместить_ декодированные инструкции в выделенный участок, корректируя адреса относительных джампов если таковые там попадаются и дополнить их там jmp'ом на следующую инструкцию оригинальной функции
3) Влепить в начало хукаемой функции jmp на свой враппер.
То есть кроме jmp'а никакого асма не требуется вообще, да и тот джамп — весьма условен

В х64 кстати все тоже самое за исключением того что выделенный участок для оригинальных инструкции желательно выделять в пределах +-2GB от хукаемой функции и помимо оригинальных релоцированных инструкций всунуть туда промежуточный полноценный джамп на свой враппер — это чтоб патчить только 5байт пролога хукаемой функции 'обычным' 5байтным джампом. А еще добавлю еще лично мой ворэраунд для некоторых некошерных хуков — декодируем и переносим по возможности 14 байт пролога, а джамп лепим 5байтный. Потому что примерно половина народу которая делает хуки пользуются 5байтными джампами по возможности, а другая половина — не заморачиваются и патчат 14байт оригинального кода. А мне приходилось дружить и с теми, и с другими и еще со многими такими что нет слов, а только маты Доходило до блокировки особо упоротых товарищей от загрузки совместно с нашим продуктом. К таким относятся к примеру любители снимать свои хуки во время жизни процесса, 'восстанавливая' пролог функции.

Вобщем сформулирую золотое правило хукинга: если ты хукаешь какую то функцию, подумай о том что получится если ктонить другой тоже похукает ее, либо до тебя либо после. Хотябы таким же способом как и ты хукаешь (об остальных способах ты узнаешь из крэшдампов )
Как много веселых ребят, и все делают велосипед...
Re[5]: Подмена CreateFile и ReadFile
От: Adnako СССР  
Дата: 10.01.14 11:47
Оценка:
Здравствуйте, Marty, Вы писали:

M>А ты http://www.rsdn.ru/forum/src/3571390.1
Автор: Marty
Дата: 16.10.09
таки внимательно смотрел? Есть там все.


омб! я как раз хочу избежать весёлых хаков с перетиранием пролога перехватываемой функции в чужой длл

M>Изменится, и что? Все точно так же будет работать. Начало функции копируется не абы как, копируются несколько первых инструкций так, чтобы на их место влез переход на патченую версию


я читал теорию
пока что компиляторы компилят системные либы так, что впихать свои 5 копеек можно, но это пока
на другой чаше весов — модификация IAT где, по идее, проблема решается элегантней и на более высоком уровне абстракций

поэтому мне бы хотелось услышать советы _опытных_ товарищей, которые боролись с IAT и имеют, что сказать про неё
в любом случае — спасибо за комментарии
Re: Подмена CreateFile и ReadFile
От: Adnako СССР  
Дата: 10.01.14 11:49
Оценка:
Добрался до названий импортируемых методов.
Оказывается не все примеры в интернете знакомы с флагом IMAGE_ORDINAL_FLAG32.
Через что и не получалось выудить IMAGE_IMPORT_BY_NAME.
Процесс идёт, ура!
Re: Подмена CreateFile и ReadFile
От: x64 Россия  
Дата: 25.01.14 21:57
Оценка:
A>Может быть кто-то уже реализовывал подобные задачи и хотя бы посоветует какую статью изучить внимательнее, чтобы добиться положительного результата.

Я так понял, ты уже нашёл проблему, но на всякий случай на этом сайте есть раздел со статьями, и среди них много довольно полезных, вот:

Перехват вызовов API
Форматы исполняемых файлов
Re: Подмена CreateFile и ReadFile
От: Аноним  
Дата: 26.01.14 11:26
Оценка:
Палевный нубский метод, ибо IAT обычно в кодосекции расположена. Ну да ладно. Есть готовый функционал — провайдер верификации(верифер), AVRF. Передаёте ему структуру описывающую апи и он пропатчит всё сам.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.