участились случаи ногебания icq по вопросу "как перехватить функцию"
в гугл слал, в лес слал, в бабруйск слал, всеравно возвращаются с вопросами
незнаю куда еще можно послать... поэтому решил описать "своими словами" чтобы слать сюда.
существует стопицот способов перехвата, у всех есть свои плюсы\минусы
опишу простейший, называется "сплайсинг"
0)
есть приложение,
компилить не надо,
просто качаем\запускаем\пробуем вложение
поциэнт.rar,
исходник такой:
c++ Код:
#include <Windows.h>
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
LoadLibrary(L"tabletka.dll"); //чтобы не засирать пример, "инжектить" лекарство будем так.
MessageBoxW(0,L"нажмите ок чтобы ботить, тока тсссс.....",L"ncsoft(c)",MB_ICONWARNING);
MessageBoxW(0,L"ботоводы, горите в аду!",L"угнова(c)",MB_ICONERROR | IDCANCEL );
return 0;
};
как мы видим, данная программа имеет некоторые недостатки,
а именно, наглые, неполиткорректные высказывания.
а так делать незя.
1)
лезем сюда _http://msdn.microsoft.com/ изучаем нужную нам функцию (ну или хотябы код в заголовках),
она выглядит так:
int __stdcall MessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);
находится тут: Minimum DLL Version
user32.dll
2)
теперь нужно научится ее вызывать хитрым способом (или изготовление функции трамплина),
делаем простой пример:
c++ Код:
DWORD addr=0;
int __stdcall jmpMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption, UINT uType)
{
__asm jmp [addr];
};
main()
{
DWORD target = (DWORD)GetProcAddress(LoadLibrary("user32.dll"),"messageboxW");
addr = target + 5; //прыгать мы будем не в "начало" функции, а на пять байт дальше.
jmpMessageBoxW(0,L"текст",L"текст", UINT uType);
};
//компилируем, убеждаемся что такая программа будет работать.
мы пропускаем часть оригинального кода, а ошибок всеравно нету, обьясняю почему.
в отладчике это будет выглядить так:
asm Код:
test.exe:10001770 jmpMessageBoxW:
test.exe:10001770 push ebp // выполняется, этот код дописал нам компилятор
test.exe:10001771 mov ebp, esp // выполняется, этот код дописал нам компилятор
test.exe:10001773 jmp ds:addr // наш джамп
test.exe:10001779 pop ebp // сюда мы никогда не попадем
test.exe:1000177A retn 10h
..
user32.dll:7E3B6534 MessageBoxW:
user32.dll:7E3B6534 mov edi, edi //пропускаем, бессмысленная инструкция, типа x=x, так захотели в майкрософт.
user32.dll:7E3B6536 push ebp //пропускаем
user32.dll:7E3B6537 mov ebp, esp //пропускаем
user32.dll:7E3B6539 cmp ds:dword_7E3C14BC, 0 //<<--мы прыгаем сюда
user32.dll:7E3B6540 jz short loc_7E3B6566
сравниваем инструкции которые мы пропустили в оригинальной функции,
и какие нам дописал компилятор в функции трамплине.
видно очень красивое "совпадение", вот какбы поэтому оно и работает.
значит если изуродовать первые 5 байт оригинальной функции, мы всеравно сможем ее вызвать.
3)
придумаем "функцию фильтр_обработчик"
c++ Код:
int __stdcall hookMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption, UINT uType)
{
int result = 0;
if(lstrcmpW(lpCaption,L"угнова(c)"))
{
//если в заголовке окна есть нецензурное слово, вызываем оригинал со своими параметрами
result = jmpMessageBoxW(hWnd, L"слава роботам!!! убить всех человеков!!", L"какой то робот(с)", MB_ICONINFORMATION);
}
else
{
//если в заголове чтото другое, ничего не трогаем, вызываем оригинал
result = jmpMessageBoxW(hWnd, lpText, lpCaption, uType);
};
return result;
};
продолжение ниже