И так, подытожим.
Стояла задача : имея исполняемый файл программы произвести перехват функций не импортируемых из внешних dll, а родом из стандартных хедеров, в частности stdio.h. Исполняемый файл собран в конфигурации Release
Вердикт: detours нам не поможет нам в этом случае, а поможет нам терпение и труд, которые, как известно все перетрут. От себя добавим, что задача это геморойная, так что лучше поискать обходные пути...
Все так?
Здравствуйте, <Аноним>, Вы писали:
А>Добрый день. В сети полно примеров перехвата апи функций. Меня заинтересовала данная тем и я наткнулся на вопрос, а как быть с функциями не импортируемыми из dll? А>1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода?
И больше того, она может быть инлайном и даже интринсиком.
Поэтому "в общем виде" такие задачи не решаются.
А в частном виде — зависит от.
Можно разжиться отладочной информацией (program database). Можно взять декомпилятор или дизассемблер. Можно расковырять исходники и подправить. Можно взять штатные точки кастомизации.
Например, перенаправить потоки ввода-вывода в твои пайпы, и делать с ними что хошь.
Поэтому расскажи о задаче, которая перед тобой стоит.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, _Dinosaur, Вы писали:
_D>>Это он динамически длину команд вычисляет? AG>
AG>To copy instructions, Detours uses a simple table-driven disassembler.
ясно
остается надеятся, что таблицы находятся в актуальном состоянии и включают недокументированные инструкции...
Завидую людям, которые могут себе позволить никуда не спешить.
Перехват вызова не WINAPI функции
От:
Аноним
Дата:
14.10.08 08:33
Оценка:
Добрый день. В сети полно примеров перехвата апи функций. Меня заинтересовала данная тем и я наткнулся на вопрос, а как быть с функциями не импортируемыми из dll?
1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода?
2. Получается мне надо лопатить сегмент кода в поисках требуемой функции?
3. Что делать дальше? В начало функции писать jump на мою функцию ?
4. Есть ли какие то средства облегчающие проведение таких операций?
Здравствуйте, Аноним, Вы писали:
А>Добрый день. В сети полно примеров перехвата апи функций. Меня заинтересовала данная тем и я наткнулся на вопрос, а как быть с функциями не импортируемыми из dll? А>1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода? А>2. Получается мне надо лопатить сегмент кода в поисках требуемой функции? А>3. Что делать дальше? В начало функции писать jump на мою функцию ? А>4. Есть ли какие то средства облегчающие проведение таких операций?
А Detours разве не умеет перехватывать функции не импортируемые из DLL?
Здравствуйте, Аноним, Вы писали:
А>Добрый день. В сети полно примеров перехвата апи функций. Меня заинтересовала данная тем и я наткнулся на вопрос, а как быть с функциями не импортируемыми из dll? А>1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода?
в случае статической линковки — да
А>2. Получается мне надо лопатить сегмент кода в поисках требуемой функции?
да. нужна сигнатура функции.
т.к. для разных сборок функция может оказаться в разных местах, то лопатить код придется...
А>3. Что делать дальше? В начало функции писать jump на мою функцию ?
да.
либо 0xCC (int 3) и ловить exception (могу ошибаться)
А>4. Есть ли какие то средства облегчающие проведение таких операций?
для поиска сигнатуры функции можно использовать IDA Pro
или дебаггеры, но потратишь больше времени
и еще сигнатуры для сборки Release и Debug скорее всего будут отличаться.
Завидую людям, которые могут себе позволить никуда не спешить.
2 remark
На счет Detours ин. Может я не внимательно читал, но я что то не увидел этого явно. Ну вообщето там написано что Detours перехватывает что хочешь...Вы уверены что это можно сделать с помощью данной библиотеки?
Здравствуйте, _Dinosaur, Вы писали:
_D>Здравствуйте, Аноним, Вы писали:
А>>Добрый день. В сети полно примеров перехвата апи функций. Меня заинтересовала данная тем и я наткнулся на вопрос, а как быть с функциями не импортируемыми из dll? А>>1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода?
_D>в случае статической линковки — да
А>>2. Получается мне надо лопатить сегмент кода в поисках требуемой функции?
_D>да. нужна сигнатура функции. _D>т.к. для разных сборок функция может оказаться в разных местах, то лопатить код придется...
А>>3. Что делать дальше? В начало функции писать jump на мою функцию ?
_D>да. _D>либо 0xCC (int 3) и ловить exception (могу ошибаться)
А>>4. Есть ли какие то средства облегчающие проведение таких операций?
_D>для поиска сигнатуры функции можно использовать IDA Pro _D>или дебаггеры, но потратишь больше времени _D>и еще сигнатуры для сборки Release и Debug скорее всего будут отличаться.
Ну хорошо что это выполнимо вообще ) но я надеюсь таки найти какие то удобные инструменты для этого ))
Здравствуйте, INsect, Вы писали:
IN>2 remark IN>На счет Detours ин. Может я не внимательно читал, но я что то не увидел этого явно. Ну вообщето там написано что Detours перехватывает что хочешь...Вы уверены что это можно сделать с помощью данной библиотеки?
detours перехватывает вставкой постоянного jmp (перезаписанный код он копирует себе, вставляя после него jmp на продолжение). см доку.
Здравствуйте, Alexander G, Вы писали:
AG>detours перехватывает вставкой постоянного jmp (перезаписанный код он копирует себе, вставляя после него jmp на продолжение). см доку.
Это он динамически длину команд вычисляет?
Завидую людям, которые могут себе позволить никуда не спешить.
Ну опишем условия задачи так:
1. Есть некая программа, необходимо подкорректировать ее поведение
2. Исходники на руках, но править их — крайний случай. не чистая работа скажем так.
3. править нужно поведение программы относительно вызова fwrite, а именно перехватывать эту функцию при вызове и в зависимости от аргументов глушить либо нет.
4. проект это ацкое поделие в borland 5-6, в лучших традициях code that smels hard)
5. сейчас рассматриваем именно такой вариант действий, других пока не предлагать...
PVOID DetourFindFunction(
PCHAR pszModule,
PCHAR pszFunction
);
Parameters
pszModule
The path of the DLL or binary in which the function should be found.
pszFunction
The name of the function to be found.
Как вы думаете почему она так лажает?
Re[3]: Перехват вызова не WINAPI функции
От:
Аноним
Дата:
14.10.08 22:04
Оценка:
IN>Как вы думаете почему она так лажает?
А может проще #define fwrite hacked_fwrite ?
Здравствуйте, Аноним, Вы писали:
IN>>Безусловно проще, но к исходному коду прикасаться нежелательно. А>А к настройкам проекта, forceinclude сделать?
Все действия, требующие пересборки проекта будут рассматриваться в последнюю очередь.
Re[7]: Перехват вызова не WINAPI функции
От:
Аноним
Дата:
15.10.08 07:18
Оценка:
IN>Все действия, требующие пересборки проекта будут рассматриваться в последнюю очередь.
Сплайсинг считается менее рисковым чем пересборка проекта. Ужас какой
Здравствуйте, Аноним, Вы писали:
IN>>Все действия, требующие пересборки проекта будут рассматриваться в последнюю очередь. А>Сплайсинг считается менее рисковым чем пересборка проекта. Ужас какой
Здравствуйте, INsect, Вы писали:
IN>Как вы думаете почему она так лажает?
Он может найти указатель по:
1. Таблице экспорта
2. Отладочной информации
Насколько я помню, Delphi не позволяет создавать .pdb файл, но он позволяет встраивать отладочную информацию в бинарник. Тогда бинарник будет в неск раз больше.
Если требуется вообще никогда не пересобирать бинарник, можно захардкодить адрес. Пересобирая, можно экспортировать этот адрес.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, INsect, Вы писали:
IN>>Как вы думаете почему она так лажает?
AG>Он может найти указатель по: AG>1. Таблице экспорта AG>2. Отладочной информации AG>Насколько я помню, Delphi не позволяет создавать .pdb файл, но он позволяет встраивать отладочную информацию в бинарник. Тогда бинарник будет в неск раз больше.
AG>Если требуется вообще никогда не пересобирать бинарник, можно захардкодить адрес. Пересобирая, можно экспортировать этот адрес.
Получается тогда, что искать придется вручную. плохо.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, INsect, Вы писали:
IN>>Получается тогда, что искать придется вручную. плохо.
AG>Вы таки хотите чтобы хак выглядел красиво ?
Здравствуйте, INsect, Вы писали:
IN>Стояла задача : имея исполняемый файл программы произвести перехват функций не импортируемых из внешних dll, а родом из стандартных хедеров, в частности stdio.h. Исполняемый файл собран в конфигурации Release IN>Вердикт: detours нам не поможет нам в этом случае, а поможет нам терпение и труд, которые, как известно все перетрут.
Поможет знание факта, что fwrite находится в некотором объектнике из поставки компилятора и линкуется в исполняетмый файл. Значит, что можно однозначно определить сигнатуру fwrite, найти функцию по ней и пропатчить (либо поставить аппаратную точку останова).
IN> От себя добавим, что задача это геморойная, так что лучше поискать обходные пути...
Это просто некрасиво, потребуется дополнительный загрузчик.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: Перехват вызова не WINAPI функции
От:
Аноним
Дата:
18.10.08 22:23
Оценка:
Здравствуйте, Аноним, Вы писали:
IN>>Все действия, требующие пересборки проекта будут рассматриваться в последнюю очередь. А>Сплайсинг считается менее рисковым чем пересборка проекта. Ужас какой
И не говори...
В соседнем топике человек готов VTBL подменять, вместо того,
чтобы сделать DLL из статической либы.
Передо мной возникла подобная проблема, поэтому хотелось бы узнать о ваших результатах,вы решили поставленную задачу?
Меня интересует поиск по сигнатурам.В книге "Искусство взлома и защиты систем" авторов Джека Козиола и Дэвида Личфилда на 299 странице описана общая методика поиска по сигнатурам.Но, честно говоря, мне все еще слабо представляется как это можно реализовать на практике.
Re: Перехват вызова не WINAPI функции
От:
Аноним
Дата:
18.12.08 07:06
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Добрый день. В сети полно примеров перехвата апи функций. Меня заинтересовала данная тем и я наткнулся на вопрос, а как быть с функциями не импортируемыми из dll? А>1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода? А>2. Получается мне надо лопатить сегмент кода в поисках требуемой функции? А>3. Что делать дальше? В начало функции писать jump на мою функцию ? А>4. Есть ли какие то средства облегчающие проведение таких операций?
. Это для тебя, просто не туда запостил.
это же перехват winapi функций!вопрос изначально стоял о перехвате функций которые не содержатся в таблице импорта.
Re[3]: Перехват вызова не WINAPI функции
От:
Аноним
Дата:
18.12.08 07:46
Оценка:
Здравствуйте, yar4i, Вы писали:
Y>Здравствуйте, Аноним, Вы писали: А>>Читай здесь
. Это для тебя, просто не туда запостил. Y>это же перехват winapi функций!вопрос изначально стоял о перехвате функций которые не содержатся в таблице импорта.
1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода?
Дык на сколько я понял задача ведь стояла перехватить что нить из stdio.h, а в частности файловые операции, просто подумал что вопрос стоит не корректно!
Здравствуйте, Аноним, Вы писали:
А>1. Ведь я так понимаю что когда в коде используется функция например из stdio.h, то в исполняемом файле она находится не в таблице импорта, а целиком помещается в сегмент кода?
да
А>Дык на сколько я понял задача ведь стояла перехватить что нить из stdio.h, а в частности файловые операции, просто подумал что вопрос стоит не корректно!
ну чтобы понятнее было поставим задачу так:мы создали Unit1.h в нем есть функция void hook_me(),так же есть еще Unit2.cpp,в котором написано:
#include "Unit1.h";
...
hook_me();
...
Так вот задача в том чтобы перехватить функцию hook_me(),при том что исходники править нельзя.
Как мне видится копать нужно в направлении поиска функций по сигнатуре.Пока я не особо накопал,поэтому и спрашиваю вашего совета.
В общем реализовал я таки сигнатурный поиск и перехват функции.Хочу поделиться кодом,может кому пригодится.На самом деле код скорее всего сыроват(еще не оптимизировал),но он работает и я, честно говоря, так счастлив что хочу скорее его опубликовать
Программа перехватывает функцию внутри самой себя,но если внедрить этот код в другой процесс,то можно перехватывать и чужие функции(если нужно внедрение могу выложить,но это отдельная песня).Итак код:
#include <stdio.h>
#include <windows.h>
#include <conio.h>
struct TInterceptInfo //структура для перехвата
{
PVOID FunctionAddr; //адрес перехватываемой функции
PVOID HookAddr; //адрес функции заменителя
byte FunctionCode[5];//первые пять байт перехватываемой функции
byte HookJmp[5]; //код с JMP
};
TInterceptInfo* LStrCpyInterceptInfo; //массив структур,int n=0; //количество структур
//функция устанавливает/убирает перехватчикbool SetHookCode(TInterceptInfo InterceptInfo,bool ASetHook)
{
bool Result=false;
DWORD OldProtect,Tmp;
int CodeSize=5;
//изменяем режим доступа к странице памяти,где содержится перехватываемая функция
VirtualProtect(InterceptInfo.FunctionAddr,CodeSize,PAGE_EXECUTE_READWRITE,&OldProtect);
if (ASetHook)
{//заменяем первые пять байт функции
Result=WriteProcessMemory(GetCurrentProcess(),InterceptInfo.FunctionAddr,
&InterceptInfo.HookJmp,CodeSize,NULL);
}
else {//убираем перехватчик
Result=WriteProcessMemory(GetCurrentProcess(),InterceptInfo.FunctionAddr,
&InterceptInfo.FunctionCode,CodeSize,NULL);
}
//возвращаем предыдущий режим доступа к странице
VirtualProtect(InterceptInfo.FunctionAddr,CodeSize,OldProtect,&Tmp);
return(Result);
}
//функция поиска последовательности байт в массиве байт
UINT FindAinB(BYTE* pbyB, BYTE* pbyA, UINT uiALen, UINT uiBLen)
{
for (int i=0;i<uiBLen;i++)
{
if (pbyB[i]==pbyA[0]){
if (memcmp(&pbyB[i], pbyA, uiALen) == 0)
return (UINT) i;
}
else continue;
}
return uiBLen;
}
//функция поиска сигнатуры и заполнения массива структур LStrCpyInterceptInfovoid Hooking(byte* signature,int length_str,TInterceptInfo* &InterceptInfo,PVOID HookFunc)
{
DWORD Tmp;
DWORD Jmp_Rel;
UINT pdest=0;
SIZE_T sizebuf=0;
byte *pointer;
byte *buffer;
char tmpstr[16]="\0";
DWORD result;
MEMORY_BASIC_INFORMATION mbi;
int m_ptr = 0;
SIZE_T readsize;
HANDLE hProcess;
hProcess=GetCurrentProcess();
//читаем постранично память процессаwhile(VirtualQueryEx(hProcess, (void *)m_ptr, &mbi, sizeof(mbi)) > 0){
buffer=(byte*)malloc(mbi.RegionSize);
readsize=0;
//всю страницу кладем в bufferif(ReadProcessMemory(hProcess,mbi.BaseAddress,buffer,mbi.RegionSize,&readsize)){
if (readsize>0)
{
//ида всегда показывала что сегмент кода начинается с этого адреса
//+ в рихтере написано что это адрес сегмента кода,ну как то так,
//собственно эту проверку можно убрать и тогда будут сканироваться все
//страницы адресного пространства процессаif (((DWORD)mbi.BaseAddress+(DWORD)mbi.RegionSize)>0x00401000) //рут функция?
{
pdest = 0;
pointer = buffer;
sizebuf = readsize;
for(;;)
{
//ищем сигнатуру
pdest = FindAinB(pointer,signature,length_str,sizebuf);
if ( pdest != sizebuf ){
//нашли сигнатуру,она находится по адресу result
result = (DWORD)mbi.BaseAddress+(pointer-buffer)+pdest;
printf( "Signature found at position 0x%08x\n", result );
//выделяем память под структуру InterceptInfo
n++;
if (n==1) InterceptInfo=(TInterceptInfo*)malloc(n);
else InterceptInfo=(TInterceptInfo*)realloc(InterceptInfo,n);
//и начинаем ее заполнять
InterceptInfo[n].FunctionAddr=(PVOID)result;
InterceptInfo[n].HookAddr=HookFunc;
//вычисление адреса на который нужно сделать jmp
//формирование 5 байт для перехвата
ReadProcessMemory(GetCurrentProcess(),InterceptInfo[n].FunctionAddr,&InterceptInfo[n].FunctionCode,5,NULL);
Jmp_Rel=(DWORD)InterceptInfo[n].HookAddr-(DWORD)InterceptInfo[n].FunctionAddr-5;
InterceptInfo[n].HookJmp[0]=0xE9;
CopyMemory(&InterceptInfo[n].HookJmp[1],&Jmp_Rel,4);
//идем дальше по буферу в поисках сигнатуры
pointer=(byte*)((int)pointer+pdest+length_str);
sizebuf=sizebuf-pdest-length_str;
}
else{
break;
}
}
}
}
}
//следующая страница
m_ptr=(int)mbi.BaseAddress+mbi.RegionSize;
free(buffer);
}
}
//перехватываемая функция копирует одну строку в другую
LPSTR my_copy(LPSTR dest,LPSTR src,int n)
{
LPSTR retval;
for (int i=0;i<n;i++) dest[i]=src[i];
dest[n]='\0';
retval=dest;
return retval;
}
//функция заменитель копирует строку задом наперед
LPSTR my_copy2(LPSTR dest,LPSTR src,int n)
{
LPSTR retval;
for (int i=0;i<n;i++) dest[i]=src[n-i-1];
dest[n]='\0';
retval=dest;
return retval;
}
int main()
{
char dest[20];
char src[]="1234";
//сигнатура my_copy
byte signature[]="\x55\x8b\xec\x81\xec\xd8\x00\x00\x00\x53
\x56\x57\x8d\xbd\x28\xff\xff\xff\xb9\x36\x00\x00\x00\xb8\xcc\xcc\xcc
\xcc\xf3\xab\xc7\x45\xec\x00\x00\x00\x00\xeb\x09\x8b\x45\xec\x83\xc0
\x01\x89\x45\xec\x8b\x45\xec\x3b\x45\x10\x7d\x12\x8b\x45\x08\x03";
int length_str=60;//ее длина
my_copy(dest,src,4); //копируем без перехватчика
printf("%s\n",dest);
//ищем сигнатуру,заменяем первые 5 байт перехватываемой функции,
//кодом перехватчика
Hooking(signature,length_str,LStrCpyInterceptInfo,&my_copy2);
SetHookCode(LStrCpyInterceptInfo[1],true);//установили хук
my_copy(dest,src,4); //копируем
printf("%s\n",dest); //но функция перехвачена и выводится результат работы my_copy2
SetHookCode(LStrCpyInterceptInfo[1],false);//сняли хук
my_copy(dest,src,4); //копируем
printf("%s\n",dest); //все хоккей!!!
free(LStrCpyInterceptInfo);
getch();
return 0;
}