Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2009.10.25;
Скачать: [xml.tar.bz2];

Вниз

Выгрузка 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 вся ветка

Форум: "WinAPI";
Текущий архив: 2009.10.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.04 c
2-1251459678
Роман
2009-08-28 15:41
2009.10.25
Остановка работы приложения


2-1250844434
cyber-pilot
2009-08-21 12:47
2009.10.25
Изменение объекта


2-1250691718
DimDim
2009-08-19 18:21
2009.10.25
Сохранение в ini


1-1220066174
Xandr001
2008-08-30 07:16
2009.10.25
Refresh в браузере


4-1219915857
sniknik
2008-08-28 13:30
2009.10.25
Как узнать кем стартуется сервис...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский