Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.10.25;
Скачать: CL | DM;

Вниз

Выгрузка WinApi перехватчика   Найти похожие ветки 

 
KygECHuK ©   (2008-08-26 10:33) [0]

занимаюсь автоматизированным тестированием, оформил плагин для перехвата отрисовки текста. он подменяет адресса к функциям в таблице импорта, в моём случае это textOut в GDI32.dll. Всё работает хорошо, вот только что при выгрузке перхватчика с некоторойй вероятностью появлятся ошибка доступа к памяти...

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


 
Сергей М. ©   (2008-08-26 11:21) [1]


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


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


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


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


 
KygECHuK ©   (2008-08-26 12:02) [2]


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

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


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


я в таком же положении - ошибка не имеет какойто опрелённой стабильности.
Иследуя проблему, пришел к выводу что ошибка МОЖЕТ появляться из-за того, что в момент выгрузки данна функция используется в основном потоке,
и соответсвенно при работе со стеком происходит оно..


 
Сергей М. ©   (2008-08-26 12:23) [3]


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


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

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


 
KygECHuK ©   (2008-08-26 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;



 
Сергей М. ©   (2008-08-26 12:45) [5]

Да.


 
KygECHuK ©   (2008-08-26 12:50) [6]

локонично :)

А моё предполежение насчёт стека может иметь какой нибуть вес?
з. ы. Сам просто только в догадках.


 
Сергей М. ©   (2008-08-26 12:51) [7]


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


Скорее нет чем да.


 
Сергей М. ©   (2008-08-26 12:54) [8]

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


 
KygECHuK ©   (2008-08-26 14:09) [9]


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

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

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

Но так или иначе, возможно следует попробывать вариант с синхронизацией доступа к целевым функцииям?


 
Сергей М. ©   (2008-08-26 15:47) [10]


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


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


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


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


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


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


 
KygECHuK ©   (2008-08-26 16:35) [11]


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


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


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

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

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

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

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


 
Rouse_ ©   (2008-08-26 16:43) [12]


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

Дык как... как обычно вестимо:
Остановить все потоки процесса за исключением своего, из которого снимаешь перехватчик. Снять перехватчик и запустить потоки далее.


 
Сергей М. ©   (2008-08-26 16:51) [13]

Ты о каких потоках ?

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

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


 
KygECHuK ©   (2008-08-26 16:51) [14]

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


 
KygECHuK ©   (2008-08-26 16:59) [15]


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


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


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


поток, котрый выгружает библиотеку и все остальные потоки.


 
Сергей М. ©   (2008-08-26 16:59) [16]


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


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


 
Сергей М. ©   (2008-08-26 17:05) [17]

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


 
KygECHuK ©   (2008-08-26 17:09) [18]


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

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

ЗЫ
 дико извиняюсь за свою некомпетентность в этой области


 
KygECHuK ©   (2008-08-26 17:10) [19]


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


Да


 
Сергей М. ©   (2008-08-26 17:21) [20]


> как тогда система реагирует на suspend


Система просто перестает выделять потоку кванты процессорного времени.
Соответственно ни одна машинструкция им не выполняется.


> что будет если такой поток востановить. он что будет переинициализован?


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

Если приложение дельфийское и для реализации GUI-интерфейса оно использует исключительно VCL-формы/контролы, можно практически со 100%-й уверенностью утверждать, что вызовы ф-ции TextOut осуществляются в основном потоке.
Крайне маловероятно, что какому-то идиоту взбредет в голову месить в одном проекте VCL-формы/контролы и создание/работа с окнами/контролами непосредственно через WinAPI)

Впрочем, этот довольно легко выяснить.


 
Сергей М. ©   (2008-08-26 17:24) [21]

Любопытно, а как ты определяешь, в каком потоке загружается/выгружается твой плагин-модуль ?

Подозреваю, что логика твоя в этой части неверна ..


 
Rouse_ ©   (2008-08-26 17:31) [22]


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

Дык эта... тормозим все что не GetCurrentThreadId в нашем процессе и всего делов :)


 
KygECHuK ©   (2008-08-26 17:32) [23]


> Любопытно, а как ты определяешь, в каком потоке загружается/выгружается
> твой плагин-модуль ?Подозреваю, что логика твоя в этой части
> неверна ..


Я пока ничего не брался определять, только советуюсь как поступить дальше
с подомным исключением.
Но предполагаю стоит вызвать GetCurrentThreadId внутри потока а по Id уже ориентироваться далее.


 
Сергей М. ©   (2008-08-26 20:24) [24]


> предполагаю стоит вызвать GetCurrentThreadId внутри потока
> а по Id уже ориентироваться далее


Ну вот получил ты Id тек.треда.
Рассказывай про твои дальнейшие действия ..


 
KygECHuK ©   (2008-08-26 22:41) [25]


> Ну вот получил ты Id тек.треда.Рассказывай про твои дальнейшие
> действия ..


* Предчуствие неладного
Беру текущий процесс и перечисляю все его потоки и сравниваю их Id c id текущего потока при помощи Toolhelp32...


 
Сергей М. ©   (2008-08-26 22:58) [26]


> Предчуствие неладного


Уже радует ..

Рассказывай как ты получил ID ОСНОВНОГО треда текущего процесса


 
KygECHuK ©   (2008-08-26 23:47) [27]


> Рассказывай как ты получил ID ОСНОВНОГО треда текущего процесса


* Чё то мне совсем сыкотно
а зачем мне определять ID ОСНОВНОГО треда текущего процесса? Или в этом есть принципиальный момент?


 
Сергей М. ©   (2008-08-27 08:17) [28]


> зачем мне определять ID ОСНОВНОГО треда текущего процесса?


Почем мне знать зачем оно тебе надо ?)

Цитирую тебя:


> функция используется в основном потоке


> синхронизировать с основным потоком


Раз ты этим озаботился, значит ты все же как-то определяешь, что такой-то поток является именно основным, а не дополнительным ?

Вот я и спрашиваю как ты это делаешь)


 
KygECHuK ©   (2008-08-27 09:39) [29]


> Почем мне знать зачем оно тебе надо ?)


Действительно....
Надёжней будет приостонавливать все потоки кроме, того что восстанавливает адреса.

Ну а если мне потребуется взять основной поток, то я просто использую GetWindowThreadProcessId от требуемого окна, ибо Delphi и VCL

Вас интересует что я имею под понятием "основной поток"? Ну наверно тот поток в котором изначально инициализирован обработчик сообщений.


 
Сергей М. ©   (2008-08-27 09:46) [30]

А что, собственно, ты тестируешь-то ? Цель какая ?


 
KygECHuK ©   (2008-08-27 10:03) [31]


> А что, собственно, ты тестируешь-то ?

АИС


>  Цель какая ?

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


 
Сергей М. ©   (2008-08-27 10:14) [32]

А что, подсистема поддержки плагинов у этой самой "АИС" не позволяет передавать в плагины требуемую тебе инф-цию ?


 
KygECHuK ©   (2008-08-27 10:26) [33]


> А что, подсистема поддержки плагинов у этой самой "АИС"
> не позволяет передавать в плагины требуемую тебе инф-цию
> ?


У АИС нет такой подсисетмы - плагин для Системы теирования.
И большая часть жалоб и замечаний именно на отображении данных в интерфейсе, а у нашей "чудо - системы" эти значения могут отличаться от расчитанных или принятых... так что следующим этапом и будет сравнение таких между различнымы способами их вывода. Собственно говоря вот и понадобился таковой плагин.


 
Сергей М. ©   (2008-08-27 10:36) [34]


> У АИС нет такой подсисетмы


Но плагины-то эта система поддерживает, раз она грузит твой плагин ?

Вот я и спрашиваю, нет ли в SDK документированных способов передать в плагин интересующую тебя инф-цию ..


 
KygECHuK ©   (2008-08-27 10:47) [35]


> Но плагины-то эта система поддерживает, раз она грузит твой
> плагин ?


Плагины поддержеивает ОТДЕЛЬНАЯ сторонняя система тетсирования.

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


 
Сергей М. ©   (2008-08-27 10:58) [36]


> ОТДЕЛЬНАЯ сторонняя система тетсирования


А как связан процесс этой системы тестирования с процессом АИС ?

Плагин-то твой, как я понимаю, грузится в АП процесса системы тестирования, а не в АП процесса АИС ..


> не спрашиваёте меня как это получается у разаработчиков


Не буду, я и так догадываюсь)


 
KygECHuK ©   (2008-08-27 11:21) [37]


> А как связан процесс этой системы тестирования с процессом
> АИС ?


Опосредованно - симулирует сообщения от лица пользователя. т. е. для системы тестирования АИС черный ящик... с одной стороны очень сложно симулировать пользователя, а с другой можно находить концептуальные ошибки и создовать наиболее ёмкие тесты.


 
Сергей М. ©   (2008-08-27 11:35) [38]


> для системы тестирования АИС черный ящик


Так а зачем же нужно перехватывать TextOut в процессе системы тестирования ? Не понимаю ..


> жалоб и замечаний именно на отображении данных в интерфейсе


Я так понял, что интерфейсе приложения АИС, а не интерфейсе приложения-тестера, которое грузит твой плагин ..


 
KygECHuK ©   (2008-08-27 11:47) [39]


> Так а зачем же нужно перехватывать TextOut в процессе системы
> тестирования ? Не понимаю ..


Приходится его немного "сломать" не сисетму же распознования писать?
Ведь данные предоставляемые АИС во время тестирования влияют на его ход.


> Я так понял, что интерфейсе приложения АИС, а не интерфейсе
> приложения-тестера, которое грузит твой плагин ..

да именно, так, приложение - тестор чисто внутренний проект

Интерфейсное приложение - красиво звучит для этой АИС оно все вместе и в одном исполняемом файле.... весит до 60 mb.


 
Сергей М. ©   (2008-08-27 12:14) [40]


> тестор чисто внутренний проект


Дельфийское ? Без исходников ?



Страницы: 1 2 3 4 5 вся ветка

Текущий архив: 2009.10.25;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.023 c
2-1251978697
Nilman
2009-09-03 15:51
2009.10.25
поменять внешний вид TComboBox


2-1251130365
andru
2009-08-24 20:12
2009.10.25
Пояснения по теме интервейсы


4-1220526205
Vlad Oshin
2008-09-04 15:03
2009.10.25
Не происходит сообщения WM_SETFOCUS,WM_KILLFOCUS


3-1228563453
Антон_207
2008-12-06 14:37
2009.10.25
курсовая


15-1249924710
Германн (из Бердянска)
2009-08-10 21:18
2009.10.25
Программка для логирования (учета) траффика