И так, подытожим.
Стояла задача : имея исполняемый файл программы произвести перехват функций не импортируемых из внешних dll, а родом из стандартных хедеров, в частности stdio.h. Исполняемый файл собран в конфигурации Release
Вердикт: detours нам не поможет нам в этом случае, а поможет нам терпение и труд, которые, как известно все перетрут. От себя добавим, что задача это геморойная, так что лучше поискать обходные пути...
Все так?
Здравствуйте, 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;
}