На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Как записать в память по адресу функции?
    Добрый день/вечер.

    У меня есть две функции:

    void __fastcall recvx_food(int This, void *Src, int len, int flags);
    и
    recvx = (recvx_f)GetProcAddress(hWS2_32, "recv");

    Как мне записать в память по адресу функции recvx
    в ноль (в самое начало) 0хE9 (jmp)
    а по смещению +1 записать адрес функции recvx_food?
    И как и куда можно сохранить первые 5 байт, чтоб потом удобно и быстро восстановить функцию recvx?
    Спасибо!
      Я как-то двояко понял вопрос, и на оба варианта ответ отрицателен. Так что может быть и третий вариант. Итак:
      А) если вы хотите, чтобы при вызове recvx(...) управление ушло куда надо и там вызвался переход на ..._food, то можете, конечно, записать: *((char*)recvx) = 0xE9, и далее нужное, но вам DEP (запись данных в код) запретить должен сие.
      Б) если же вы хотите, чтобы при вызове recvx(...) сразу шло исполнение jmp куда_надо, то тоже не выйдет, ибо переменную положат, скажем, в EAX и будет вызвано call [EAX], т.е. не то, что хотелось.
      В) ???
        Цитата Славян @
        но вам DEP (запись данных в код) запретить должен сие.

        я заюзал VirtualProtectEx
        Если оба варианта не подходят, то как хукнуть ws2_32 recv? Как его хукают обычно? Я бы сплайсингом хотел... Никак?

        Цитата
        *((char*)recvx) = 0xE9, и далее нужное

        Я вот и спросил - как далее то? Я синтаксис Си плохо знаю...
        *((char+1*)recvx) или *((char*)[1]recvx) или как?))
        Сообщение отредактировано: Rzonex -
          Да, вам нужен вариант А.
          Почти как у вас: ((char*)recvx)[1] = первый байт, и т.д.
          Или сразу адрес: *((DWORD*)(((char*)recvx)+1)) = 0xAaBbCcDd;
            Славян Спасибо.
            А получится сплайсингом функцию хукнуть если у нее в конце джамп? Мне же после работы оригинала надо снова хук ставить, а управление уплыло неизвестно куда...

            Перехватить получилось, а если восстанавливать хук после вызова оригинала - ловлю крит. Видимо из за джампа в конце ws2_32 recv.
            Не хукают сплайсингом функции с джампом? Или я кривой?
            Сообщение отредактировано: Rzonex -
              Цитата Rzonex @
              А получится сплайсингом функцию хукнуть если у нее в конце джамп?

              Через таблицу импорта попробуй.
                А как ее найти? Именно адрес начала таблицы? Я читал описание РЕ, но нифига не понял. Шерстил длл, так то на практике видел что она в памяти представляет, но не нашел...
                Я если честно, то уже хукнул, очень оригинально) Суть моего метода такая:

                1) обрабатываем оригинальную функцию виртуал-протектом.
                2) делаем AllockMem и резервируем буфер байт на 20.
                3) пишем в начало нашего буфера (смещение 0х00) CALL функция_обработчик
                4) копируем в наш буфер со смещением 0х05 первые 5 байт оригинальной функции
                5) пишем в буфер со смещением 0х10 джамп на ( оригинальную функцию +0х05 )
                6) пишем в начало оригинальной функции джамп на наш буфер.

                Вуаля, как только основной поток вызывает оригинальную функцию - он попадает на наш джамп и летит по адресу нашего буфера, в буфере он сразу же летит на наш обработчик хука,
                там мы делаем свои дела и ретурном возвращаемся в буфер, далее выполняем инструкции оригинальной функции (которые мы скопировали) и джампимся в оригинал + 0х05.
                Профит, салют, аплодисменты :D

                Это я сам так придумал хукать по нубски) А если честно, то язык на котором программирую, не поддерживает ассемблерные вставки, приходится вот так изголяться. Таблицу экспорта в тыщу раз было бы легче похукать.
                И еще я не восстанавливал ни указатель на стек, ни регистры, ни сам стек после обработчика своего, оно (вот чудо) и так заработало.
                  Цитата Rzonex @
                  А как ее найти? Именно адрес начала таблицы? Я читал описание РЕ, но нифига не понял.
                  ...
                  4) копируем в наш буфер со смещением 0х05 первые 5 байт оригинальной функции
                  5) пишем в буфер со смещением 0х10 джамп на ( оригинальную функцию +0х05 )
                  6) пишем в начало оригинальной функции джамп на наш буфер.
                  ...
                  далее выполняем инструкции оригинальной функции (которые мы скопировали) и джампимся в оригинал + 0х05.

                  в этой теме почти полный исходник.
                  Там же есть ссылка на статью в Сети.
                  У Рихтера в книге есть пример.
                  ---
                  А откуда ты знаешь, что 5 байт кратны целому числу команд ?
                  Чтобы с гарантией эти мероприятия делать, надо буквально
                  дизассемблер иметь в перехватчике.
                  Сообщение отредактировано: ЫукпШ -
                    Цитата ЫукпШ @
                    А откуда ты знаешь, что 5 байт кратны целому числу команд ?

                    OllyDbg юзаю. Я же не пытаюсь сделать что-то универсальное, для этого моих познаний еще маловато.
                      Сделал читалку РЕ файлов, в начальный адрес добавил адрес нужной dll в памяти $10000000, вот что получил:

                      ExpandedWrap disabled
                        =========================================
                        Process ID                : 4816
                        Base addr                 : 00000000h
                        PE signature              : 00004550h
                        Processor type            : 0000014Ch
                        Section count             : 00000005h
                        Date of create            : 1386212911
                        Addr export table         : 000DC4F0h
                        Size of export table      : 104080
                        Addr import table         : 000D6D8Ch
                        Size of import table      : 420


                      Прибавил к адресам таблиц адрес dll, получилось адрес таблицы экспорта: 100DC4F0.
                      Перешел по адресу попал на vftable, но там же должны идти адреса функций, а там явно какой то вменяемый asm код, а не адреса...
                      Это разве оно?
                      user posted image
                        Цитата Rzonex @
                        Сделал читалку РЕ файлов, в начальный адрес добавил адрес нужной dll в памяти $10000000, вот что получил:

                        Прибавил к адресам таблиц адрес dll, получилось адрес таблицы экспорта: 100DC4F0.
                        Перешел по адресу попал на vftable, но там же должны идти адреса функций, а там явно какой то вменяемый asm код, а не адреса...

                        Наверное, мы не поняли друг друга.
                        1. Менять надо адрес в таблице импорта исполнительного
                        модуля (любого - .exe или .dll) одного по выбору
                        или у всех сразу.
                        В PE файле есть таблица с адресами.
                        Для вызова функции делается что-то вроде:
                        call [addr] - т.е. вызов по содержимому указанной переменной в памяти.

                        2. Как это сделать подробно написано в широко известной
                        книге Рихтера. У него же в книге подробный исходник.
                        Мой опус по ссылке - это исходник Рихтера с добавкой,
                        необходимой для систем после Win2000.
                        3. Запускаем подопытный процесс с внедрённой своей dll.
                        Внедряем как нравится. Можно внешним стартёром, можно
                        утилитой "iidking" вставить ссылку на свою dll
                        в таблицу импорта подсудимого файла.
                        Если наше приложение, цепляем dll обычным образом.
                        Для начала и отладки инструмента можно сделать именно так.
                        4. Из уведомления DLL_PROCESS_ATTACH перехватываем
                        указанный API. Фактически, в таблицу импорта
                        впишем адрес процедуры перехватчика, а из неё
                        вызовем нужную процедуру самым обычным образом.
                        В результате получим процедуру-посредника.
                        ---
                        Это устойчиво работает для любых виндусов и для x64 версий тоже.
                        Без ассемблера, реверсных исследований. Надо только знать
                        прототип желаемой функции и всё.
                        ---
                        Вот, кстати, внешний стартёр для инжекта своей dll в процесс.
                        Который я сам написал:
                        dllInjector
                        Сообщение отредактировано: ЫукпШ -
                          Цитата ЫукпШ @
                          Наверное, мы не поняли друг друга.

                          Addr import table : 000D6D8Ch
                          Size of import table : 420
                          Оно? Делал по описанию РЕ файла - Структура EXE заголовка
                          Я читал что и экспорт можно патчить? А какая разница? Просто он тут маленького размера, я решил что быстрее найду нужное в экспорте :D

                          Цитата
                          Без ассемблера, реверсных исследований.

                          А чем мой способ плох? Я же нашел адреса таблиц, это же они? Притом это делается довольно просто - находим адрес нужной библиотеки, считываем пару адресов в памяти и получаем нужный адрес.
                          Внутри процесса это совсем просто сделать - LoadLibraryA, GetProcAddress, и прыгаем по смещениям читаем адреса...
                          Притом без всяких библиотек.
                          Сообщение отредактировано: Rzonex -
                            Нашел все адреса экспортируемых функций, и их адреса в таблице экспорта.
                            Все данные нашел путем парсинга PE формата. Внутри процесса такую операцию можно сделать вообще не используя WinApi. Это профит, я КОРОЛЬ!!! :D (Король аськи!!!) :D
                            Насколько я понял - если патчить ипморт, то нужно патчить все таблицы импорта во всех модулях, искать импортируется ли туда эта функция и менять адрес.
                            Это сложновато выглядит. А если сама длл использует свою экспортируемую функцию? Тогда хук не сработает и надо патчить экспорт?

                            Одно не понимаю - все адреса функций в экспорте внутренние для самой длл, то есть смещение у них от начала длл задано. Я к ним специально адрес длл прибавлял, чтоб получить глобальный адрес.
                            Что будет, если я локальный адрес какой-нить функции заменю глобальным адресом своей хук функции? По идее мне и сам хук нужно размещать внутри этой длл, но MemAlloc мне там память же не выделит?
                            Хотя можно 5 байт пустых найти в самой длл и сделать обертку - разместить там джамп на сам обработчик.

                            ЫукпШ подскажи куда копать???

                            user posted image
                            Сообщение отредактировано: Rzonex -
                              Цитата Rzonex @
                              Насколько я понял - если патчить ипморт, то нужно патчить все таблицы импорта во всех модулях, искать импортируется ли туда эта функция и менять адрес.
                              Это сложновато выглядит.

                              Это зависит от того, чего именно ты желаешь добиться.
                              И ничего сложного тут нет.
                              Это потребует 2-3 строчки исходника.
                              Допустим, ты написал функцию перехвата:
                              ExpandedWrap disabled
                                // pModName    - имя модуля, в котором перехватываем API в импорте
                                // pDllNames   - имя dll, в которой перехваченный API
                                // pApiName    - имя перехваченной функции
                                // pRoutine    - адрес функции подмены
                                //
                                BOOL WINAPI HookApi
                                (
                                 const char* pModName,
                                 const char* pDllName,
                                 const char* pApiName,
                                 void*        pRoutine
                                );

                              А дальше составляешь массив параметров для неё.
                              И запускаешь в цикле. Парой строк подменишь всё, что нужно.
                                ЫукпШ Я хукаю функцию в модуле Engine.dll и эта функция юзается там же, этим же модулем. Импорт я не смотрел, но очень сильно подозреваю, что этой функции там нет. Что делать? :)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0466 ]   [ 17 queries used ]   [ Generated: 19.03.24, 05:18 GMT ]