Конференция "WinAPI" » Выгрузка WinApi перехватчика [D7, WinXP]
 
  • KygECHuK © (26.08.08 10:33) [0]
    занимаюсь автоматизированным тестированием, оформил плагин для перехвата отрисовки текста. он подменяет адресса к функциям в таблице импорта, в моём случае это textOut в GDI32.dll. Всё работает хорошо, вот только что при выгрузке перхватчика с некоторойй вероятностью появлятся ошибка доступа к памяти...

    Возможно кто нибудь занимался подомной проблематикой и может что нибудь посоветовать...
  • Сергей М. © (26.08.08 11:21) [1]

    > подменяет адресса к функциям в таблице импорта


    Для полноценного перехвата в произвольном приложении этого недостаточно - необходим еще и перехват соотв.записей в EAT.


    > с некоторойй вероятностью появлятся ошибка доступа к памяти


    Слишком мало инф-ции для анализа.
  • KygECHuK © (26.08.08 12:02) [2]

    > Для полноценного перехвата в произвольном приложении этого
    > недостаточно - необходим еще и перехват соотв.записей в
    > EAT.

    Здесь, пожалуйста, поподробней...


    > Слишком мало инф-ции для анализа.


    я в таком же положении - ошибка не имеет какойто опрелённой стабильности.
    Иследуя проблему, пришел к выводу что ошибка МОЖЕТ появляться из-за того, что в момент выгрузки данна функция используется в основном потоке,
    и соответсвенно при работе со стеком происходит оно..
  • Сергей М. © (26.08.08 12:23) [3]

    > поподробней


    Вызывающий модуль вправе и может получить адрес т.входа в требуемую подпрограмму вызываемого модуля и прямо в ран-тайм, т.е. с пом. a-wbb GetProcAddress, которая как раз и обращается к EAT вызываемого модуля.

    Отсюда вывод - либо модифицировать EAT, либо перехватывать в IAT вход в GetProcAddress с целью подмены оригинальных адресных значений из EAT требуемыми адресами точек входа.
  • KygECHuK © (26.08.08 12:39) [4]

    > либо перехватывать в IAT вход в GetProcAddress с целью подмены
    > оригинальных адресных значений из EAT требуемыми адресами
    > точек входа.

    Вы имеете ввиду следующее ?
    function MyLoadLibraryA(
     pszModuleName: pChar
     ): HMODULE; stdcall;
    begin
     sm_pInstance.funcEvent.ResetEvent;
      // debug
     sm_pInstance.funcEvent.CurFuncName := 'MyLoadLibraryA';
     //

     try
      Result := LoadLibraryA(pszModuleName);
       TModuleScope(sm_pModuleScope).LogMessage(pChar('Подгружена библиотека :' + pszModuleName));
      TApiHookMgr.HackModuleOnLoad(Result, 0);
     finally
       sm_pInstance.funcEvent.setEvent;
     end
    end;

    class procedure TApiHookMgr.HackModuleOnLoad(hmod: HMODULE; dwFlags: Cardinal);
    var
     lockMgr : TLockMgr;
     i       : Integer;
     Hook    : THookedFunction;
    begin
    // Если был загружен новый модуль то тоже вставим перехватчик
    if ((hmod <> 0) and ((dwFlags and LOAD_LIBRARY_AS_DATAFILE) = 0)) then
    begin
     lockMgr := TLockMgr.Create(sm_CritSec, TRUE);
       try
       for i := 0 to sm_pHookedFunctions.Count - 1 do
         begin
           Hook := sm_pHookedFunctions[i];
        Hook.ReplaceInOneModule(
         Hook.CalleeModName,
         Hook.pfnOrig,
         Hook.pfnHook,
         hmod
         );
       end; // for
       finally
         lockMgr.Free;
       end;
    end // if
    end;

    function MyGetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
    var
     lockMgr  : TLockMgr;
     pfn      : pointer;
     FuncHook : THookedFunction;
    begin
      sm_pInstance.funcEvent.ResetEvent;
      // debug
     sm_pInstance.funcEvent.CurFuncName := 'MyGetProcAddress';
     //

     try

       lockMgr := TLockMgr.Create(sm_CritSec, TRUE);
       try
         // получение оргинального адресса функции
         pfn := Pointer(TApiHookMgr.GetProcAddressWindows(hModule, lpProcName));
         //  попытка найти если функция была сломана
         FuncHook :=
           sm_pHookedFunctions.GetHookedFunction(
             hModule,
             lpProcName
             );

         if (nil <> FuncHook) then
           // возаращаем адрес перехваченной функции
           pfn := FuncHook.pfnHook;
         Result := pfn;
       finally
         lockMgr.Free;
       end;
     finally
       sm_pInstance.funcEvent.setEvent;
     end;

     TModuleScope(sm_pModuleScope).LogMessage(pChar('В библиотеке :' + GetModuleName(hModule) +
                                                    ' запрошена функция :'+ lpProcName));

    end;


  • Сергей М. © (26.08.08 12:45) [5]
    Да.
  • KygECHuK © (26.08.08 12:50) [6]
    локонично :)

    А моё предполежение насчёт стека может иметь какой нибуть вес?
    з. ы. Сам просто только в догадках.
  • Сергей М. © (26.08.08 12:51) [7]

    > предполежение насчёт стека может иметь какой нибуть вес?


    Скорее нет чем да.
  • Сергей М. © (26.08.08 12:54) [8]
    Вне сомнения лишь одно - пока выполняется код, принадлежащий адр.пространству, занимаемому модулем, выгружать этот модуль недопустимо.
  • KygECHuK © (26.08.08 14:09) [9]

    > Вне сомнения лишь одно - пока выполняется код, принадлежащий
    > адр.пространству, занимаемому модулем, выгружать этот модуль
    > недопустимо.

    это понятно, вот только под выгрузкой ловушки я подразумевал замену подстваленных адресов на оригинальные, если я вас правильно понял.

    я насильственно ни один модуль не выгражую.

    Но так или иначе, возможно следует попробывать вариант с синхронизацией доступа к целевым функцииям?
  • Сергей М. © (26.08.08 15:47) [10]

    > под выгрузкой ловушки я подразумевал замену подстваленных
    > адресов на оригинальные


    Выгрузкой это назвать никак нельзя.


    > насильственно ни один модуль не выгражую


    А как он, модуль, у тебя вообще попадает в АП "жертвы" ?


    > синхронизацией доступа к целевым функцииям?


    если ты не выгружаешь модуль из АП процесса-"жертвы" вплоть до его завершения, то синхронизация вряд ли имеет смысл.
  • KygECHuK © (26.08.08 16:35) [11]

    > А как он, модуль, у тебя вообще попадает в АП "жертвы" ?


    Да, действительно.. сдесь я напутал (тока из месячного отпуска вышел :) )...
    Надо будет на этим подумать


    > если ты не выгружаешь модуль из АП процесса-"жертвы" вплоть
    > до его завершения, то синхронизация вряд ли имеет смысл.
    >

    приложение в основном и работает с активным выводом текстовой информации и если перехватчик вовремя не выгрузить, это приведёт  к  потере производительности. И хочется сделать плагин правильно..

    в купе с вашим предыдущим замечанием и моим стремлением удачно выгрузить модуль получается, что поток выгружающий библиотеку действительно придеться синхронизировать с основным потоком, чтобы оградить и АП.

    То конечно умозрительный вывод, но на данный момент он мне кажеться наиболее правдоподомным....

    Вот только как сделать синхронизацию с чужим потоком? Пока ума не приложу...
  • Rouse_ © (26.08.08 16:43) [12]

    > Вот только как сделать синхронизацию с чужим потоком? Пока
    > ума не приложу...

    Дык как... как обычно вестимо:
    Остановить все потоки процесса за исключением своего, из которого снимаешь перехватчик. Снять перехватчик и запустить потоки далее.
  • Сергей М. © (26.08.08 16:51) [13]
    Ты о каких потоках ?

    Приложение чужое, заранее знать из какого потока будет осуществляться загрузка/выгрузка твоего модуля ты не можешь, как не можешь и заранее знать из каких потоков будут вызываться ф-ции, которые ты перехватил.

    Что и с чем ты собрался "синхронизировать", я пока не понимаю ..
  • KygECHuK © (26.08.08 16:51) [14]
    С потоками мало имел дела, а по сему вопрос есть гарантия что при остановке стороних потоков они не будут использовать требуемого АП?
    Т.е остановяться в этом АП , а при попыке их восстановить получим, то же исключение?
  • KygECHuK © (26.08.08 16:59) [15]

    > Приложение чужое, заранее знать из какого потока будет осуществляться
    > загрузка/выгрузка твоего модуля ты не можешь, как не можешь
    > и заранее знать из каких потоков будут вызываться ф-ции,
    >  которые ты перехватил.


    Плагин для тестировния интерфесных форм, по первому приблежению должно хватить потока, которы обработывает сообщения требуемой формы, хотя о достаточности такого подхода утверждать не берусь.


    > Что и с чем ты собрался "синхронизировать", я пока не понимаю
    > ..


    поток, котрый выгружает библиотеку и все остальные потоки.
  • Сергей М. © (26.08.08 16:59) [16]

    > при остановке стороних потоков они не будут использовать
    > требуемого АП?


    Разумеется не будут.
  • Сергей М. © (26.08.08 17:05) [17]
    Приложение-то дельфийское ?
  • KygECHuK © (26.08.08 17:09) [18]

    > Разумеется не будут.

    Что то я не понимаю...
    А как тогда система реагирует на suspend
    и что будет если такой поток востановить. он что будет переинициализован?

    ЗЫ
     дико извиняюсь за свою некомпетентность в этой области
  • KygECHuK © (26.08.08 17:10) [19]

    > Приложение-то дельфийское ?


    Да
 
Конференция "WinAPI" » Выгрузка WinApi перехватчика [D7, WinXP]
Есть новые Нет новых   [134435   +33][b:0.001][p:0.003]