| 
			| 
					
						| Aether | 
								|  | «  : 04-08-2016 11:39 »  |  | 
 
 Добрый день.
 Спрошу, возможно, кто-то уже сталкивался. Для получения списка функций содержащегося в DLL существуют утилиты, например, tiny_impdef, но, как быть, если в DLL содержится COM объект? Естественно, некоторые из функций, явно объявленные в библиотеке, будут являться создателями некоего базового интерфейса, однако, сколько интерфейсов всего? И второе, у интерфейса есть методы - как построить их таблицу? Третье, является ли позиция того или иного метода в vtable статической, или она может "изменяться"?
 
 Какую современную литературу по COM стоит изучить?
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #1 : 04-08-2016 12:58 »  |  | 
 
 Для зарегистрированных в системе компонент можно посмотреть в панели управление/администрирование/компоненты. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #2 : 04-08-2016 16:48 »  |  | 
 
 Поясню на примере: есть a.dll. Создаю a.def. Внутри оказывается много чего, но меня интересует функция Create_A_interface(...), которая возвращает интерфейс IA. Как я уже понял, интерфейс - это всего лишь указатель на vtable, который является списком указателей на методы данного COM объекта, соответственно, если мне нужен метод IA_start, то мне нужно не просто знать его имя, а знать его позицию в этом vtable. Изучение заголовочных файлов приводит к конструкции вида: STDMETHOD(IA_start)(...), которая как-то не очень понятно разворачивается... В общем, первое, что захотелось осуществить: узнать механизм распознавания методов? Или ситуацию более полно?
 И ещё, в параметры Create_A_interface входит GUID - 128 бит идентификатор. Если я буду туда посылать не записанный в a.h, GUID_A, а GUID от IUnknown, то соответственно, должен ли я на выходе получить IUnknown от этого COM объекта? Или это зависит от реализации конкретной функции получения интерфейса?
 
 Извиняюсь за сумбурность, пытаюсь разобраться впервые.
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| zubr 
								Гость
 | 
								|  | « Ответ #3 : 04-08-2016 23:07 »  |  | 
 
 Aether, не имея описания методов, по одной длл - тут только реверс поможет. А так, если есть описание, получил интерфейс вызовом Create_A_interface - это и есть адрес vtable. Зная номер нужного метода, исходя из описания умножаешь его на размер указателя (32/64 бита) - получаешь адрес указателя, который содержит адрес метода. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #4 : 05-08-2016 05:39 »  |  | 
 
 Из описания только заголовочный файл, но он, как понял годится только для MSVC, так как в нём не нахожу явного присваивания методам номеров. Единственное, что есть, конструкции вида:STDMETHOD ...(QueryInterface)(...)
 STDMETHOD ...(Addref)(...)
 STDMETHOD ...(Release)(...)
 Про эти три прочёл уже, что они идут следом строго в одной последовательности, то есть позиции 0, 1, 2. Предположу, что остальное тоже по списку, и буду пробовать.
 Другое дело, каков нормальный путь к распознаванию или какое описание должно поставляться? Иначе как быть, если нет желания пользоваться MSVC или нужно что-то перевести на asm?
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| zubr 
								Гость
 | 
								|  | « Ответ #5 : 05-08-2016 07:07 »  |  | 
 
 В описании, как правило, последовательность методов, соответствует их в vtable. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #6 : 06-08-2016 07:54 »  |  | 
 
 Да, предположение оказалось правильное: позиции в списке заголовочного файла совпадают с позициями методов в VTable. Вообще очень странная конструкция: для вызова функции необходимо несколько служебных обращений к памяти, и несмотря на работу внутри одного модуля, каждому методу нужно передавать ещё и сам интерфейс. Ладно, главное, что работает.   |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| zubr 
								Гость
 | 
								|  | « Ответ #7 : 06-08-2016 20:32 »  |  | 
 
 Фишка в том, что у com-интерфейса могут быть абстрактные методы, которые ты можешь реализовать сам - отсюда и такая конструкция. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #8 :  07-08-2016 10:05 »   |  | 
 
 Фишка в том, что у com-интерфейса могут быть абстрактные методы, которые ты можешь реализовать сам - отсюда и такая конструкция.
 Если возможно, то на примере. Код приводить не нужно, просто для понимания. На настоящий момент я понимаю так: COM связан с Windows, поэтому внутренняя реализация останется закрытой, по крайней мере, что-то добавить можно лишь там, где это дадут сделать. Второе: как часть DLL редактирование VTable, например, для переадрессации на свою функцию невозможно. Мало того, GUID уникален для каждого интерфейса, и должен оставаться таким. В целом понимаю так: если придерживаться этой концепции, то писать нужно собственный компонент, связывая его известными интерфейсами с другими. Выпуская новую версию компонента, необходимо, присваивать ей новый GUID. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Dale | 
								|  | « Ответ #9 : 07-08-2016 10:41 »  |  | 
 
 Когда-то давно, когда еще работал с COM, ответы на все возникающие вопросы находил в этой книге: http://www.softzenware.com/downloads/inside_com.pdf Полистайте, может, и на Ваши вопросы она ответит. |  
						| 
								|  |  
								|  |  Записан | 
 
 Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
 Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
 
 Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
 |  |  | 
	| 
			| 
					
						| zubr 
								Гость
 | 
								|  | « Ответ #10 : 07-08-2016 12:04 »  |  | 
 
 Если возможно, то на примере. Код приводить не нужно, просто для понимания. На настоящий момент я понимаю так: COM связан с Windows, поэтому внутренняя реализация останется закрытой, по крайней мере, что-то добавить можно лишь там, где это дадут сделать. Второе: как часть DLL редактирование VTable, например, для переадрессации на свою функцию невозможно. Мало того, GUID уникален для каждого интерфейса, и должен оставаться таким. В целом понимаю так: если придерживаться этой концепции, то писать нужно собственный компонент, связывая его известными интерфейсами с другими. Выпуская новую версию компонента, необходимо, присваивать ей новый GUID.К примеру, если надо перехватить события IE, а точнее интерфейса IWebBrowser2, который наследуется от интерфейса IDispath, создается класс наследник IDispath и переопределяется метод Invoke. На низком уровне мы просто получаем адрес этого метода (ведь длл уже загружена в память нашего процесса), и при его выполнении мы получаем нужные параметры, которые уже вставляем в свой метод, к примеру в событие OnDocumentDownload. И почему невозможна переадресация на свою функцию. Находишь в памяти процесса vtable, а данная таблица содержит указатели на методы, что мешает туда прописать адреса на свои функции? Ну только естественно потом надо будет вернуть управление на оригинальный адрес метода. Я такое как-то реализовывал с DirectShow через инжект, причем с чужим процессом. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #11 : 07-08-2016 18:15 »  |  | 
 
 И почему невозможна переадресация на свою функцию. Находишь в памяти процесса vtable, а данная таблица содержит указатели на методы, что мешает туда прописать адреса на свои функции? Я так понимаю, VTable находится в пространстве DLL, и как-то оно должно быть защищено, ведь то, что мы изменим там, измениться и для других задач, её использующих? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| zubr 
								Гость
 | 
								|  | « Ответ #12 : 08-08-2016 03:55 »  |  | 
 
 Никак не защищено, да и никак и не защитишь - вся защита установка флагов не для записи, только ничего не мешает изменить протектшион.Естественно, если будешь делать хак vtable, то надо предусмотреть, чтобы только в нужных тебе случаях выполнялся подмененный код.
 
 З.Ы. Подмену то надо делать уже в процессе, когда длл загружена туда, а не в самом файле длл, тем более в самом файле это бессмысленно.
 |  
						| 
								|  |  
								| « Последнее редактирование: 08-08-2016 03:57 от zubr » |  Записан | 
 |  |  | 
	|  |