Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];

Вниз

Перехват API методом исправления таблиц импорта.   Найти похожие ветки 

 
zXm ©   (2006-08-19 09:55) [0]

Здарствуйте. Столкнулся с необходимостью перехватывать вызовы некоторых функций в моей програме. Зделал перехват с помощью сплайсинга функцию(замена первых 5 байт на переход по адресу функции обработчика), но проблема в том что такой способ перехвата не работает если функция меньше 5 байт. К сожелению, одна из перехватываемых функций слишком малленькая. нашёл функцию на с осуществляющую замену адресов в таблице импорта. Просьба переделать на делфи(я пытался но безуспешно) или найти её готовую на делфи. Думаю это будет интересно не только мне.
ЗЫ Про int 3 просьба не рассказывать - знаю, но не подходит.

void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
 PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller)
{
 //Получим адрес секции импорта
 ULONG ulSize;
 PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
   (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hmodCaller, TRUE,
   IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
 if (pImportDesc == NULL)
   return;  //Здесь её нет
 //Найдём нужный модуль
 for (; pImportDesc->Name; pImportDesc++)
 {
   PSTR pszModName = (PSTR)((PBYTE) hmodCaller + pImportDesc->Name);
   if (lstrcmpiA(pszModName, pszCalleeModName) == 0)
   {
     //Нашли
     if (pImportDesc->Name == 0)
       return;  //Ни одна функция не импортируется
     //Получим адрес таблицы импорта
     PIMAGE_THUNK_DATA pThunk =
       (PIMAGE_THUNK_DATA)((PBYTE) hmodCaller + pImportDesc->FirstThunk);
     //Переберём все импортируемые функции
     for (; pThunk->u1.Function; pThunk++)
     {
       PROC* ppfn = (PROC*) &pThunk->u1.Function; //Получим адрес функции
       BOOL fFound = (*ppfn == pfnCurrent);     //Его ищем?
       if (!fFound && (*ppfn > sm_pvMaxAppAddr))
       {
         // Если не нашли, то поищем поглубже.
         // Если мы в Win98 под отладчиком, то
         // здесь может быть push с адресом нашей функции
         PBYTE pbInFunc = (PBYTE) *ppfn;
         if (pbInFunc[0] == cPushOpCode)
         {
           //Да, здесь PUSH
           ppfn = (PROC*) &pbInFunc[1];
           //Наш адрес?
           fFound = (*ppfn == pfnCurrent);
         }
       }

       if (fFound)
       {
         //Нашли!!!
         DWORD dwDummy;
         //Разрешим запись в эту страницу
         VirtualProtect(ppfn, sizeof(ppfn), PAGE_EXECUTE_READWRITE, &dwDummy);
         //Сменим адрес на свой
         WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
           sizeof(pfnNew), NULL);
         //Восстановим атрибуты
         VirtualProtect(ppfn, sizeof(ppfn), dwDummy , &dwDummy);
         //Готово!!!
         return;
       }
     }
   }
 }
 //Здесь этой функции не нашлось
}


 
zXm ©   (2006-08-19 20:12) [1]

Нашёл функцию на делфи:

uses Windows,TlHelp32;

type
_IMAGE_IMPORT_DESCRIPTOR = packed record
case Integer of 0: (
Characteristics: DWORD);
1: (
OriginalFirstThunk: DWORD;
TimeDateStamp: DWORD;
ForwarderChain: DWORD;
Name: DWORD;
FirstThunk: DWORD);
end;
IMAGE_IMPORT_DESCRIPTOR = _IMAGE_IMPORT_DESCRIPTOR;
PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
PFARPROC = ^FARPROC;

function ImageDirectoryEntryToData(Base: Pointer; MappedAsImage: ByteBool;DirectoryEntry: Word; var Size: ULONG): Pointer; stdcall; external "ImageHlp.dll";

function ReplaceIATEntryInOneMod(pszCallerModName:Pchar; pfnCurrent:FarProc; pfnNew:FARPROC; hmodCaller:hModule):Boolean;
var
ulSize:ULONG;
pImportDesc:PIMAGE_IMPORT_DESCRIPTOR;
pszModName:PChar;
pThunk:PDWORD;
ppfn:PFARPROC;
ffound:LongBool;
written:DWORD;
begin
result:=false;
pImportDesc := ImageDirectoryEntryToData(Pointer(hmodCaller),TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,  ulSize);
if pImportDesc = nil then exit;
while pImportDesc.Name <> 0 do
 begin
  pszModName := PChar(hmodCaller + pImportDesc.Name);
  if (lstrcmpiA(pszModName, pszCallerModName) = 0) then break;
  Inc(pImportDesc);
 end;
if (pImportDesc.Name = 0) then exit;
pThunk := PDWORD(hmodCaller + pImportDesc.FirstThunk);
while pThunk^ <> 0 do
 begin
  ppfn:= PFARPROC(pThunk);
  fFound:=(ppfn^ = pfnCurrent);
  if (fFound) then
   begin
    VirtualProtectEx(GetCurrentProcess, ppfn, 4, PAGE_EXECUTE_READWRITE,Written);
    WriteProcessMemory(GetCurrentProcess, ppfn, @pfnNew, sizeof(pfnNew),Written);
    VirtualProtectEx(GetCurrentProcess, ppfn, 4, PAGE_EXECUTE_READWRITE,Written);
    exit;
   end;
  Inc(pThunk);
 end;
result:=true;
end;

Проверил, хука работает с приложениями из виндоус, но на моём тестовом примере в делфе нет. В той же статье прочитал следующую фразу:
"Тест, написанный на Visual C++, работал прекрасно – функция GetDriveTypeA перехватывалась. А вот программа на Delphi всё равно для всех перехватываемых мной дисков возвращала реальные значения. Я посмотрел таблицу импорта тестовой программы при помощи утилиты DUMPBIN и обнаружил, что компилятор Delphi не поместил все импортируемые функции из kernel32.dll в один список, а разбил их на 3 части, причём GetDriveTypeA оказалась в третьей. Поэтому функция ReplaceIATEntryInOneMod Джеффри Рихтера, просмотрев все функции из первого списка Kernel32.dll, не нашла функции GetDriveTypeA, хотя она и импортировалась модулем DriveTypeTest.exe. Я исправил эту функцию таким образом, чтобы она проверяла всю таблицу импорта и перебирала все списки с функциями из kernel32.dll (как оказалось, их может быть несколько). В описании формата РЕ-файла нигде не оговаривается, что каждый модуль, из которого импортируются функции, должен встречаться в секции импорта только один раз, и, видимо, некоторые компиляторы этим пользуются."

Однако приведёная там функция соответсвует функции приведённой Джеффри Рихтером. Вобщем вопрос что нужно подправить. Чтобы перехват работал везде.


 
zXm ©   (2006-08-19 22:27) [2]

Всё всем спс. Ответ найден.


 
Сергей М. ©   (2006-08-21 08:55) [3]

Для полноценного перехвата недостаточно модификации одной лишь IAT - следует модифицировать еще и EAT.

EAT используется при вызове GetProcAddress(), т.е. при динамическом импорте. Если не модифицировать эту таблицу, то ф-ция всегда будет возвращать адрес оригинальной точки входа.


 
GrayFace ©   (2006-08-25 22:28) [4]

Поэтому Рихтер советует перехватывать и ее. Могу привести код DigitMan"а, меняющий не IAT и EAT, но мне кажется, что игра не стоит свечь - для EAT и код большой, и недокументированные особенности использует, и блок экспортов библиотеки в своп идет.


 
GrayFace ©   (2006-08-25 22:29) [5]

GrayFace ©   (25.08.06 22:28) [4]
не IAT и EAT

"не" лишнее.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.01 c
15-1166292829
<[exe-cutt3r]>
2006-12-16 21:13
2007.01.07
Задачи по D7


1-1163766674
Mishenka
2006-11-17 15:31
2007.01.07
Как в Word вставить картинку не поверх текста?


2-1166358355
Apachi
2006-12-17 15:25
2007.01.07
как можно уменьшить размер компилируемой DLL


3-1161460608
Nik76
2006-10-21 23:56
2007.01.07
Как предотвратить автоматическое обновление поля?


2-1166438378
unn[a]med^
2006-12-18 13:39
2007.01.07
ADO help me plz)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский