Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как по дескриптору окна или ещё чему-нить получить сам экземпляр [D6, WinXP]


Страницы:   1 2

Pashka.cool ©   (2006-07-18 12:53:00) 

Как по дескриптору окна или ещё чему-нить получить сам экземпляр. Например я могу получить методом GetClassName имя класса. Но необходим экземпляр.


Игорь Шевченко   (2006-07-20 10:19:00) [1]

Leonid Troyanovsky ©   (20.07.06 00:28) [26]


> а вдруг, скажем, функции system компилируются
> по одним и тем же адресам.


Проверялось. По разным. Из-за умного линкера, не включающего в окончательный код неиспользуемые функции :)


Leonid Troyanovsky   (2006-07-20 00:28:00) [2]


> Игорь Шевченко ©   (19.07.06 23:59) [25]

>  но если имеется map-файл целевого EXEшника на Delphi, то
> данный способ имеет право на существование.


Да, конечно. Но тоже нехилое ограничение.

И вот, стало любопытно (никогда раньше не задумывался),
а вдруг, скажем, функции system компилируются
по одним и тем же адресам. Надо будет проверить :)

--
Regards, LVT.


Игорь Шевченко   (2006-07-19 23:59:00) [3]

Leonid Troyanovsky ©   (19.07.06 23:53) [23]

Некий Свен Шрайбер обходил подобные моменты (вызов неэкспортируемых функций) путем анализа файла символов целевого EXE-модуля. Правда, у него в качестве EXE-модуля выступал NTOSKRNL.EXE для которого получить файл символов было довольно легко, но если имеется map-файл целевого EXEшника на Delphi, то данный способ имеет право на существование.


Johnmen   (2006-07-19 23:59:00) [4]

Удалено модератором
Примечание: Offtopic


Leonid Troyanovsky   (2006-07-19 23:53:00) [5]


> Leonid Troyanovsky ©   (19.07.06 23:04) [20]

> некий универсальный thunk для вызова любых (или, наиболее


Утопия.
Бо, из dll нам не узнать, какой адрес в екзешнике имеет,
например SetString, т.к., наружу он не торчит.

--
Regards, LVT.


Leonid Troyanovsky   (2006-07-19 23:25:00) [6]


> begin...end ©   (19.07.06 23:14) [21]

> Об этом написано в [15].


Честно говоря, более интересовало
> Кстати, что, в D7 оно уже не хранится aka property (GetProp)?

Потому, как со времен D3 туда (FindControl) не заглядывал.

--
Regards, LVT.


begin...end   (2006-07-19 23:14:00) [7]

> Leonid Troyanovsky ©   (19.07.06 23:04) [20]

> А почему, собс-но, не тот же FindControl?
Об этом написано в [15].

Сорри, но продолжать дискуссию в этой ветке настроения уже нет. Ещё раз извините.


Leonid Troyanovsky   (2006-07-19 23:04:00) [8]


> begin...end ©   (19.07.06 18:00) [12]


>    // Получение идентификатора сообщения RM_GETOBJECTINSTANCE
>    GetSystemDirectory(SysDir, sizeof(SysDir));
>    Message := RegisterWindowMessage(PChar(Format('ControlOfs%.
> 8X%.8X', [GetModuleHandle(PChar(SysDir + '\vcl70.bpl')),
>  GetCurrentThreadId])));

А почему, собс-но, не тот же FindControl?
Кстати, что, в D7 оно уже не хранится aka property (GetProp)?

>  UnhookWindowsHookEx(H);

Здесь я б тоже добавил PostMessage(.., WM_NULL..),
чтобы длл реально отцепилась.

> ссылки, вызовы статических методов, чтение и изменение свойств,
>  работу с VMT и RTTI. Снимается ловушка вызовом RemoveHook.

Было б любопытно проанализировать, какие именно препятствия
мешают применению того же RTTI в условиях безпакетной компиляции.

Или, скажем по-другому, насколько ограничительны требование
использовать пакеты.
Например, сабклассируем искомое окно, вписываем в экзешник
некий универсальный thunk для вызова любых (или, наиболее
распространенных) методов и вызываем их, скажем, путем
SendMessage.

Хотя, конечно, это чисто академический интерес :)

--
Regards, LVT.


begin...end   (2006-07-19 22:56:00) [9]

> Юрий Зотов ©   (19.07.06 22:52) [18]

Предлагаю на этой пессимистической ноте закончить оффтопик. Начатый, кстати, Вами.


Юрий Зотов   (2006-07-19 22:52:00) [10]

Значит, так ничего и не поняли. Что ж, комментарии действительно излишни.


begin...end   (2006-07-19 22:33:00) [11]

> Юрий Зотов ©   (19.07.06 21:54) [16]

> Поскольку код столь же очевиден, сколь и бесполезен.

Тем не менее, он является ответом на [11] -- Вы сами захотели его увидеть. Зачем просить то, что для Вас заведомо бесполезно, известно только Вам.

------------------------

В [4] Вы даёте ответ, который в общем случае неверен. Почему Вы даёте именно такой ответ -- известно, опять же, только Вам.

В [5] Вас поправляют. Без всяких наездов, крошения батонов и качения баллонов -- просто вносят уточнение в Ваш ответ.

В [6] Вы благодарите за уточнение.

В [11] (спустя полдня) Вы заявляете, что [6] -- это была шутка. Ну, шутка так шутка -- она, правда, совсем не смешная, ну да не важно. И одновременно с этим просите привести пример, подтверждающий уточнение [5] -- причём просите так, как будто сомневаетесь в том, что [5] вообще может быть верным.

В [12] Вы это подтверждение, тем не менее, получаете.

А в [16] заявляете, что это подтверждение бесполезно.

------------------------

Думаю, после ТАКОЙ цепочки событий комментарии излишни. Скажу лишь, что авторитет -- штука, конечно, хорошая, и поэтому терять его не хочется. Но иногда его может спасти честность. Чего Вам и желаю.


Юрий Зотов   (2006-07-19 21:54:00) [12]

Уговорили, забираю поздравление назад. Действительно, поздравлять тут не с чем. Поскольку код столь же очевиден, сколь и бесполезен.

А насчет "ошибки" в [4] - Вы хоть поняли, почему был дан именно такой ответ?


begin...end   (2006-07-19 21:26:00) [13]

> Юрий Зотов ©   (19.07.06 20:40) [14]

> И все это, конечно же, о целевом приложении заранее известно

Иногда бывает известно.

> А самому внедренному коду остается всего лишь использовать
> RM_GETOBJECTINSTANCE (свежая мысль, что и говорить).

Внедрённый код может использовать и FindControl. В [12] я его не использовал намеренно, т.к. мне показалось, что так сам механизм будет нагляднее -- хорошо видно, что ранее сообщение зарегистрировал именно пакет.

> Это именно то, что он хотел.

Вам, несомненно, виднее -- Вы ещё в [4] предположили, что автор может пытаться искать контрол в чужом процессе.

Подводя итог, скажу, что своё утверждение [5] по Вашей просьбе в [11] я подтвердил реальным кодом [12]. Правда, вместо обещанной признательности услышал в ответ неуместный сарказм -- объяснить это можно только Вашим нежеланием признать свою ошибку, которая в [4] всё же была (и [12] это подтверждает).

P.S. Ваше поздравление позвольте переадресовать обратно Вам -- в таких "поздравлениях" я не нуждаюсь.


Юрий Зотов   (2006-07-19 20:40:00) [14]

> begin...end ©   (19.07.06 18:03) [13]

Угу. Именно с run-time пакетами. Причем оба приложения. Причем именно с одними и теми же run-time пакетами. Естественно, одних и тех же версий. Естественно, включая и пакеты B> стороннихкомпонентов (а то вдруг там какой-нибудь TMyEdit используется?).

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

Поздравляю. Вне всяких сомнений, Вы очень помогли автору вопроса в решении его задачи. Это именно то, что он хотел. Таким образом, Ваш постинг [5] в контексте данной ветки был более чем уместен.


begin...end   (2006-07-19 18:03:00) [15]

P.S. Пример написан для Delphi 7 и был проверен на Win2k.


begin...end   (2006-07-19 18:00:00) [16]

> Юрий Зотов ©   (18.07.06 21:08) [11]

> То, что в [6] была шутка - это Вы, надеюсь, поняли.

То, что в [5] была НЕ шутка -- это Вы, надеюсь, тоже поняли.

> Для получения ссылки на чужой экземпляр TWinControl по хэндлу
> его окна идентичность версий Delphi даже не обязательна.

"Спасибо за информацию" (с). Я где-то утверждал, что для получения ссылки на экземпляр необходима идентичность версий Delphi? Плз, буду весьма признателен, если Вы укажете соответствующий номер поста. Я же, просмотрев ветку, вижу лишь одно моё упоминание об этом -- в [5], где ясно сказано, что идентичность необходима для решения задачи автора. Его задачей является получение самого экземпляра (и, вероятно, дальнейшая работа с ним), а не ссылки на него. Так вот -- для решения этой задачи идентичность версий Delphi действительно необходима.

> Легко могу привести пример, в котором приложение, написанное
> на D7 получает совершенно правильную ссылку на TEdit, который
> находится в приложении, написанном на D6.

Потрясён Вашими знаниями, однако смею заверить, что это, как ни странно, могу сделать и я.

> Но вот за пример полноценного использования этой ссылки
> (как Вы утверждаете в [8]) был бы весьма признателен.

Если целевое приложение и та программа, которую планируется использовать для решения авторской задачи, собраны в одной и той же версии Delphi, то, в полном согласии с моим утверждением [5], задача автора МОЖЕТ ОКАЗАТЬСЯ решаемой . Для того, чтобы она ОКАЗАЛАСЬ решаемой , необходимо выполнение ещё одного условия: оба приложения должны быть собраны с runtime-пакетами.

И такой пример полноценного (на мой взгляд) использования ссылки я приведу. Механизм примера довольно прост -- пишется DLL, которая хуком внедряется в ВАП целевого процесса. Если и DLL, и EXE-файл  процесса собраны в одинаковых версиях Delphi, причём с runtime-пакетами, никаких трудностей не возникнет -- например, при вызове одного и того же метода из EXE и DLL управление будет передаваться в одно и то же место пакета, отображённого на ВАП.

Код библиотеки таков:

library Project2;

uses
 SysUtils, Classes, Windows, Messages, Forms, TypInfo;

type
 THackForm = class(TForm);

var
 H: HHOOK;

function HookProc(code, wp, lp: Integer): LRESULT; stdcall;
var
 Message, Handle: Cardinal;
 I, PropCount: Integer;
 PropList: PPropList;
 Properties: string;
 SysDir: array[0..MAX_PATH] of Char;
 Self: TForm;
 Obj: TObject;
begin
 if PMsg(lp).message = WM_NULL then
 begin
   Handle := PMsg(lp).wParam;

   // Получение идентификатора сообщения RM_GETOBJECTINSTANCE
   GetSystemDirectory(SysDir, sizeof(SysDir));
   Message := RegisterWindowMessage(PChar(Format('ControlOfs%.8X%.8X', [GetModuleHandle(PChar(SysDir + '\vcl70.bpl')), GetCurrentThreadId])));

   // Получение указателя на экземпляр класса
   Self := TForm(SendMessage(Handle, Message, 0, 0));

   if Assigned(Self) then
   begin
     MessageBox(Handle, PChar(IntToHex(Integer(Self), 8)), 'Адрес экземпляра в чужом ВАП', 0);

     // Проверка работы System._IsClass
     Obj := Self;
     if Obj is TComponent then
       MessageBox(Handle, PChar('Форма является потомком TComponent'), '_IsClass', 0);

     // Чтение свойства
     MessageBox(Handle, PChar(Self.Name), 'Имя формы', 0);

     // Вызов классового метода
     MessageBox(Handle, PChar(String(Self.ClassName)), 'Имя класса формы', 0);

     // Получение списка published-свойств
     PropCount := GetTypeData(Self.ClassInfo).PropCount;
     GetMem(PropList, PropCount * sizeof(PPropInfo));
     try
       GetPropList(Self, PropList);
       Properties := '';
       for I := 0 to Pred(PropCount) do
       begin
         if I mod 5 = 0 then
           Properties := Properties + sLineBreak;
         Properties := Properties + ' ' + PropList[I].Name;
       end;
       MessageBox(Handle, PChar(Properties), 'Published-свойства', 0);
     finally
       FreeMem(PropList);
     end;

     // Вызов виртуального метода
     THackForm(Self).ChangeScale(1, 2);

     // Запись свойства
     Self.Caption := 'Через 3 секунды форма будет скрыта';

     // Вызов статического метода
     Sleep(3000);
     Self.Hide;
     Sleep(2000);
     Self.Caption := 'А сейчас она опять видна';
     Self.Show;
   end;
 end;
 Result := CallNextHookEx(0, code, wp, lp);
end;

procedure SetHook(FormHandle: Cardinal);
var
 ThreadId: Cardinal;
begin
 ThreadId := GetWindowThreadProcessId(FormHandle);
 H := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, HInstance, ThreadId);
 Win32Check((H <> 0) and PostThreadMessage(ThreadId, WM_NULL, FormHandle, 0));
end;

procedure RemoveHook;
begin
 UnhookWindowsHookEx(H);
end;

exports
 SetHook, RemoveHook;

begin
end.


С хост-приложением DLL общается с помощью двух функций -- SetHook и RemoveHook. После вызова SetHook с дескриптором окна "чужой" формы в качестве параметра библиотека сразу же делает всю работу -- демонстрирует значение полученной ссылки, вызовы статических методов, чтение и изменение свойств, работу с VMT и RTTI. Снимается ловушка вызовом RemoveHook.

Впрочем, чтение/запись свойств, вызов статических методов и корректный поиск в VMT можно, за исключением частных случаев, организовать и без пакетов. Например, в случае статического метода в ВАП процесса после внедрения DLL окажется ДВА аналогичных участка (аналогичных -- в силу идентичности версий) с кодом метода -- один из них будет вызываться из хост-приложения, другой -- из DLL. А вот с RTTI в отсутствие пакетов, разумеется, будут проблемы.

Пример написан на скорую руку (менее чем за час), поэтому тщательно я его не проверял, однако думаю, что свою задачу -- демонстрацию доступа к чужому экземпляру -- он выполняет.


Юрий Зотов   (2006-07-18 21:08:00) [17]

> begin...end

1. То, что в [6] была шутка - это Вы, надеюсь, поняли. Поскольку очевидно, что модуль Controls смотрели не только Вы (причем давным-давно).

2. Для получения ссылки на чужой экземпляр TWinControl по хэндлу его окна идентичность версий Delphi даже не обязательна. Легко могу привести пример, в котором приложение, написанное на D7 получает совершенно правильную ссылку на TEdit, который находится в приложении, написанном на D6. Впрочем, даже и пример не обязателен - достаточно сравнить всего лишь одну строковую константу все в тех же модулях Controls.

3. Естественно, полученная из чужого АП ссылка валидна для чужого же АП. Естественно, в него можно и внедриться. Но вот за пример полноценного использования этой ссылки (как Вы утверждаете в [8]) был бы весьма признателен.

Примечание:слово "полноценное", естественно, означает, что во внедренном в чужой процесс коде с полученной ссылкой можно работать точно так же, как мы это делаем в "родном" коде. Включая работу с VMT и RTTI.


begin...end   (2006-07-18 19:01:00) [18]

> DrPass ©   (18.07.06 18:54) [9]

Речь идёт о чужом адресном пространстве, которое на время внедрения в процесс становится своим.


DrPass   (2006-07-18 18:54:00) [19]


> Внедрение в процесс ещё не отменили

Я так понимаю, речь о чужом адресном пространстве в таком случае не идет? :)


begin...end   (2006-07-18 18:40:00) [20]

> DrPass ©   (18.07.06 18:37) [7]

Смысл заключается в полноценном его использовании. Внедрение в процесс ещё не отменили.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо