Вернуться   CoderX :: Forums > Основные форумы > Программинг
Войти через OpenID

Программинг Форум для тем связанных с программированием

Чат (Новых сообщений с момента вашего последнего визита нет)
Загрузка...
Задавайте ваши вопросы на форуме. Чат предназначен для небольших разговоров.
 
Ответ
 
Опции темы Опции просмотра
Старый 29.01.2010, 23:01   #1
Рыцарь
 
Аватар для destructor
 
Регистрация: 26.06.2009
Сообщений: 2,433
Сказал Спасибо: 154
Имеет 692 спасибок в 426 сообщенях
destructor на пути к лучшему
По умолчанию хуки для самых маленьких

участились случаи ногебания 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 &#91;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; };


продолжение ниже
__________________
Шожиделать.. ботить хочется..

Последний раз редактировалось destructor, 29.01.2010 в 23:13.
destructor вне форума   Ответить с цитированием
За это сообщение destructor нажился 7 спасибками от:
Старый 29.01.2010, 23:03   #2
Рыцарь
 
Аватар для destructor
 
Регистрация: 26.06.2009
Сообщений: 2,433
Сказал Спасибо: 154
Имеет 692 спасибок в 426 сообщенях
destructor на пути к лучшему
По умолчанию

4)
собственно сам "сплайсинг"
идея заключается в том чтобы в начале оригинальной функции записать "jmp куда_нам_надо" и тогда поциэнт будет вызывать "то_что_нам_надо"

код инструкции jmp xxxxx выглядит так:
1байт опкод 0xe9 + 4 байта смещение(какраз 5 байт, тоже "совпадение"),
"смещение" означает сколько байт нам надо перепрыгнуть,
если нам надо прыгнуть на 500 байт вперед, пишем туда 500,
если нам 300 байт назад пишем туда -300.

вычеслить нужное нам значение нужно так:
v = targetaddr - posjmpaddr;
targetaddr, адрес куда надо прыгнуть (в нашем случае это адрес hookMessageBoxW)
posjmpaddr, адрес инструкции jmp + ее размер (+5 байт).

тоесть,
c++ Код:
//делаем доступной память для записи. target = (DWORD)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxW"); VirtualProtect((void*)target,PAGE_EXECUTE_READWRITE,10,&oldprotect); //вычисляем адрес куда будем писать опкод: BYTE * pE9 = (BYTE*)target; //вычисляем адрес, куда будем писать смещение DWORD * pofset = (DWORD*)(pE9+1); //пишем в память: *pE9 = 0xe9; *pofset = (DWORD)hookMessageBoxW - (target+5);


5)
собираем в кучу написанное выше и оформляем в виде длл:
c++ Код:
#include <Windows.h> //трамлин DWORD addr; int __stdcall jmpMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption, UINT uType) {     __asm jmp &#91;addr]; }; //обработчик int __stdcall hookMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption, UINT uType) {        int result = 0;     if(lstrcmpW(lpCaption,L"угнова(c)")==0)     {         //если в заголовке окна есть нецензурное слово, вызываем оригинал со своими параметрами         result = jmpMessageBoxW(hWnd, L"слава роботам!!! убить всех человеков!!", L"какойто робот(с)", MB_ICONINFORMATION);     }     else     {         //если в заголове чтото другое, ничего не трогаем, вызываем оригинал         result = jmpMessageBoxW(hWnd, lpText, lpCaption, uType);     };     return result; }; BOOL WINAPI DllMain( HINSTANCE hModule,DWORD  Reason, LPVOID lpReserved ) {     DWORD target;     DWORD oldprotect;     BYTE * pE9;     DWORD * pofset;     switch(Reason)     {     case DLL_PROCESS_ATTACH:         target = (DWORD)GetProcAddress(GetModuleHandleW(L"user32.dll"),"MessageBoxW");         if(!VirtualProtect((void*)target,10,PAGE_EXECUTE_READWRITE,&oldprotect))return FALSE; // а вдруг?         //настраиваем трамплин         addr = target + 5; //прыгать мы будем не в "начало" функции, а на пять байт дальше.         //правим оригинал, в начало записываем джамп на наш обработчик         pE9 = (BYTE*)target;         pofset = (DWORD*)(pE9+1);         *pE9 = 0xe9;         *pofset = (DWORD)hookMessageBoxW - (target+5);            break;         case DLL_PROCESS_DETACH:         //тут выгрузка длл         //надо восстановить оригинальный код функции,         //но нам по*уй, такой херней страдают только в конец задроченные ботаны,         //а все чоткие праграмисты знают что "меньше кода = меньше багов"         break;     };     return TRUE; };
жмем компилить, должна получится tabletka.rar
теперь если рядом с нашим поциэнтом положить таблетку, мы сможем наблюдать чудесное исцеление.

какашками кидацо незя, т.к. это часный\стерильный случай
__________________
Шожиделать.. ботить хочется..

Последний раз редактировалось destructor, 29.01.2010 в 23:32.
destructor вне форума   Ответить с цитированием
За это сообщение destructor нажился 7 спасибками от:
Старый 30.01.2010, 00:29   #3
Admin!
 
Аватар для xkor
 
Регистрация: 04.08.2007
Сообщений: 2,360
Сказал Спасибо: 113
Имеет 1,566 спасибок в 651 сообщенях
xkor на пути к лучшему
По умолчанию

destructor, то что первые 5 байт совпали в этом примере эт конечно хорошо, но это довольно редкий случай и охрененно упрощающий код притом. А вот если первые 5 байт не совпадают, то начинается веселье, надо переместить первые инструкции (естественно целое количество инструкций) которые заполняют первые 5 или больше байт куданить себе в массив и ещё дописать в массив джамп на оригинальную функцию (со смещением равным количеству списанных из начала байт), оформить этот массив как имеющий возможность быть выполненным (ну VirtualProtect'ом обработать опять же), а вот уже дальше записать на место первых 5 байт оригинала джамп, ну и в своей функции вместо оригинала уже вызывать не оригинал со смещением, а наш массив.
ЗЫ и эт ещё хорошо если мы можем функцию перехватываемую в дизассемблере посмотреть и посчитать сколько байт занимает целое число команд в начале, а если не можем то надо ещё как то программно это определять...
__________________
Я здесь практически не появляюсь!, Skype - ikskor
xkor вне форума   Ответить с цитированием
За это сообщение xkor нажился 3 спасибками от:
Старый 30.01.2010, 00:47   #4
Местный
 
Регистрация: 08.05.2008
Сообщений: 107
Сказал Спасибо: 6
Имеет 12 спасибок в 6 сообщенях
finomen пока неопределено
По умолчанию

по теме [W A S M . R U] СТАТЬИ ? Секреты Win32 ? Перехват API функций в Windows NT (часть 1). Основы перехвата.
__________________
Intel® Core™2 Duo Processor E6400 @ 2.64GHz
Nvidia GeForce 9800GT
3 G Ram
1T HDD
Gentoo Linux x64
finomen вне форума   Ответить с цитированием
Старый 30.01.2010, 01:08   #5
Местный
 
Аватар для SeregaZ
 
Регистрация: 16.08.2009
Сообщений: 1,224
Сказал Спасибо: 4
Имеет 229 спасибок в 182 сообщенях
SeregaZ пока неопределено
По умолчанию

а есть идея как экспорер перехватывать? точней html контент. потом перекраивать как надо - и подсовывать эксплореру как нивчем небывало?
сейчас перед запуском своей программы я ставлю в файлик hosts этот сайт, и "редиректом" на 127.0.0.1 - где, собственно, поднимается маленький веб сервер. браузер в результате не замечает и работает, думая что все нормально... вот хотелось бы, пускай вирусоподобно, подменять этот адрес в самом эксплорере, без редактирования файла hosts. и при этом чтобы сохранялись всякие keep alive соединения будь то форум, веб аська, или чат.
SeregaZ вне форума   Ответить с цитированием
Старый 30.01.2010, 01:17   #6
Местный
 
Регистрация: 08.05.2008
Сообщений: 107
Сказал Спасибо: 6
Имеет 12 спасибок в 6 сообщенях
finomen пока неопределено
По умолчанию

1) напиши проксик и запихай в настройки эксплорера
2) хук на send\recv (см. исходники l2ph)
3) драйвер-фильтр сетевого интерфейса

и на что еще хватит больного воображения....если поделишься конкретной задачей-может будут более адекватные мысли.
__________________
Intel® Core™2 Duo Processor E6400 @ 2.64GHz
Nvidia GeForce 9800GT
3 G Ram
1T HDD
Gentoo Linux x64
finomen вне форума   Ответить с цитированием
Старый 30.01.2010, 16:02   #7
Местный
 
Аватар для SeregaZ
 
Регистрация: 16.08.2009
Сообщений: 1,224
Сказал Спасибо: 4
Имеет 229 спасибок в 182 сообщенях
SeregaZ пока неопределено
По умолчанию

хороший пример proxomitron. работает как прокси сервер и фильтр. туда засунул по шаблону к примеру рекламу бегуна - и на всех сайтах, где он её встретит - отрезает.
но там все фильтры открыты и нужно браузер настраивать на работу как с прокси. а мне хотелось бы эти самые фильтры спрятать, а все настройки автоматизировать. притом proxomitron, и современные её аналоги типа proximodo - уже не развиваются, закрыты сто лет назад. и основная проблема подвисает чуть чуть.
поэтому хотел бы сделать нечто вроди плагина для IE, который бы занимался этим самым редиректом по началу, и как развитие идеи - перекраиванием по шаблону как proxomitron.
SeregaZ вне форума   Ответить с цитированием
Старый 30.01.2010, 17:16   #8
Рыцарь
 
Аватар для destructor
 
Регистрация: 26.06.2009
Сообщений: 2,433
Сказал Спасибо: 154
Имеет 692 спасибок в 426 сообщенях
destructor на пути к лучшему
По умолчанию

Цитата:
Сообщение от xkor Посмотреть сообщение
но это довольно редкий случай
такие совпадения это довольно частый случай,
во всех основных винапи майкрософт специально дали нам эти 5 байт (добавли 2 nop в начале),
Цитата:
Сообщение от xkor Посмотреть сообщение
и охрененно упрощающий код притом.
ну тут какбы ключевая фраза




Цитата:
Сообщение от xkor Посмотреть сообщение
или больше байт куданить себе в массив и ещё дописать в массив джамп на оригинальную функцию
я "массив" готовлю так:
c++ Код:
int __stdcall jmpMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption, UINT uType) { __asm nop __asm nop __asm nop __asm nop __asm nop __asm nop __asm nop __asm jmp &#91;addr]; };
адрес jmpMessageBoxW это начало "массива",
потом просто делаю копипасту нужного количества инструкций:
memcpy(jmpMessageBoxW,MessageBoxW, X);
и все, код не сильно усложняется
__________________
Шожиделать.. ботить хочется..

Последний раз редактировалось destructor, 30.01.2010 в 17:19.
destructor вне форума   Ответить с цитированием
За это сообщение destructor нажился 3 спасибками от:
Старый 08.05.2010, 23:43   #9
Пользователь
 
Регистрация: 03.11.2008
Сообщений: 60
Сказал Спасибо: 3
Имеет 107 спасибок в 21 сообщенях
GoldFinch пока неопределено
По умолчанию

Для реальных ситуаций, надо либо смотреть какие инструкции в начале функции и прописывать их в jmpMessageBoxW() руками,
либо использовать дизассемблер длин инструкций и определять длину и тип копируемых инструкций с его помощью.

Также надо учитывать что когда в начало функции пишется "jmp hook", то если какой-то поток в это время исполняет код в этом месте - прога упадет, по этому либо надо быть уверенным что никакие потоки эту часть кода исполнять не будут, либо замораживать все потоки, проверять это и если надо - переносить eip на новый код.

Дизассемблер длин инструкций, адаптированный для VC++ можно посмотреть тут
http://code.google.com/p/nabla-kb/so...s/rce/hook.cpp
(функция instruction_length, пропустить сложно; остальной код в этом сорце работает только частично)
GoldFinch вне форума   Ответить с цитированием
За это сообщение GoldFinch нажился спасибкой от:
Старый 09.05.2010, 23:26   #10
Местный
 
Аватар для Yegor
 
Регистрация: 05.04.2009
Сообщений: 1,436
Сказал Спасибо: 306
Имеет 122 спасибок в 98 сообщенях
Yegor пока неопределено
По умолчанию

Кто то поделится секретом, какую функцию в л2 (руоф) хукать для того чтобы можно было получить копию готового, расшифрованного пакета?
__________________
Продажа чистых аккаунтов 4G, L2 EU, AARu, AA EU, Aion EU, Tera RU, Tera EU (ICQ 594297609)
Продажа VK авторег аккаунтов (ICQ 594297609)
Yegor вне форума   Ответить с цитированием
Ответ

  CoderX :: Forums > Основные форумы > Программинг


Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 02:42.

vBulletin style designed by MSC Team.
Powered by vBulletin® Version 3.6.11
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Locations of visitors to this page
Rambler's Top100

Вы хотите чувствовать себя в безопасности? чоп Белган обеспечит её!