Текущий архив: 2007.01.07;
Скачать: CL | DM;
Вниз
Перехват 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 вся ветка
Текущий архив: 2007.01.07;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.009 c