Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги хакеры / Защита_от_взлома_сокеты,_эксплойты,_shell_код_Фостер_Дж_

.pdf
Скачиваний:
14
Добавлен:
19.04.2024
Размер:
3.68 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

-xcha

1.

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

2.

3.

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Добавление СОМ расширений в программу RPCDUMP 691

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

-x cha

 

 

 

Первый параметр шаблона – это Base, его значением является интер-

df

 

e

 

 

 

 

 

 

n

 

 

 

 

фейс, который должен реализовать энумератор. Обычно в качестве интерфейса указывается IEnumXXXX, а в нашем случае – IEnumVARIANT. Собственно, интерфейса с именем IEnumXXXX не существует, всегда нужно вместо XXXX указывать конкретный тип возвращаемых значений.

Следующий параметр – это IID интерфейса, который должен реализовать класс. Как видно из набора классов, которым наследует CComEnumOnSTL, последний реализует объекты, создаваемые с помощью CComObject. Ясно, что раз речь идет о классе компонента, то должен быть реализован интерфейс IUnknown и, что самое важное, метод QueryInterface. Но для этого необходимо знать IID запрашиваемого интерфейса. В нашем случае он задается с помощью конструкции

&__uuidof(IEnumVARIANT).

Следующий параметр T – это фактический тип данных, возвращаемых энумератором. Эта информация необходима энумератору, так как она используется в одном из реализуемых им методов:

STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched);

4.Четвертый параметр – это политика копирования, которой будет придерживаться ATL. Поскольку в своей внутренней структуре энумератор хранит STL-вектор, то нужно каким-то образом установить связь между типом данных, хранящихся в векторе, и типом данных, возвращаемых энумератором. В данном случае мы отображаем IFACE_DATA_ENTRY на VARIANT. Параметр, определяющий политику копирования, – это класс, реализующий три метода: copy, init и destroy.

5.Пятый параметр – это тип STL-контейнера, которому принадлежит член кокласса с именем m_coll. Обычно при реализации энумераторов этот член инициализируется еще до возврата указателя на интерфейс энумератора клиенту.

В строках 915 определен тип класса, реализующего набор, – EndpointCollectionType. Отметим, однако, что одного этого класса недостаточно для создания класса компонента. Иными словами, его нельзя передать в качестве параметра шаблону CComObject, поскольку в нем не задана потоковая модель и отсутствует реализация IDispatch. В строках 18–30 приведена фактическая реализация кокласса EndpointCollectionType.

Òèï EndpointCollectionType – это конкретизация шаблона ICollectionOnSTLImpl, определенного следующим образом:

template <class T, class CollType, class ItemType, class CopyItem, class EnumType>

class ICollectionOnSTLImpl : public T

692 Глава 13. Написание компонентов для задач, связанных с безопасностью

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

 

 

 

 

 

 

7. Первый параметр этого шаблона – интерфейс, который должна реали--x cha

 

e

 

 

 

 

df

 

 

n

 

 

 

 

 

 

 

 

 

 

зовать конкретизация ICollectionOnSTLImpl, точно так же, как в определении энумератора выше. В данном случае мы указали интерфейс IEndpointCollection.

8. Второй параметр – это тип STL-контейнера, которому принадлежит поле m_coll класса, описывающего набор.

9. Третий параметр – это тип данных, возвращаемый методом Item интерфейса набора.

10. Четвертый параметр – это политика копирования из STL-контейнера в аргумент, передаваемый методу Item. Мы должны выполнить преобразование из типа IFACE_DATA_ENTRY в IEndpoint*.

11. Пятый параметр – это класс энумератора (рассмотренный выше). Объект такого класса возвращается методом _NewEnum. Мы указали, что должен использоваться ранее определенный тип EnumType.

Теперь, когда все необходимые определения имеются, можно реализовать класс набора (строки 18–30):

В строках 18–23 заданы атрибуты кокласса. Как видим, этот кокласс пользуется моделью с раздельными потоками и не может быть создан непосредственно путем вызова CoCreateInstance.

В строке 25 сказано, что кокласс наследует реализации IDispatchImpl интерфейса IDispatch и в качестве параметра этого шаблонного класса указан тип набора EndpointCollectionType.

В примере 13.8 показана реализация главного класса CRPCDump.

Пример 13.8. Реализация кокласса CRPCDump (из файла COMSupport.cpp)

1 [

2coclass,

3threading("apartment"),

4vi_progid("RPCDump.Scanner"),

5version(1.0),

6 uuid("8B680433-A2BE-491E-B2CF-F858C1C16A93")

7 ]

8 class ATL_NO_VTABLE CRPCDump :

9public IDispatchImpl<IRpcEnum>

10{

11public:

12HRESULT Execute(BSTR bstrTarget, IEndpointCollection **ppResult)

13{

14// Проверить корректность аргументов

15if (!bstrTarget || !ppResult)

16return E_POINTER;

17

18 // pArg[0] – путь к модулю

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

 

 

-

 

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

 

 

 

e

 

 

 

 

d

 

 

xch19

 

 

 

 

 

 

 

f-

 

an

 

 

 

 

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Добавление СОМ расширений в программу RPCDUMP 693

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

// pArg[1] – целевой хост

 

 

 

df-x chan

e

 

 

 

 

 

 

 

USES_CONVERSION;

CHAR szModule[MAX_PATH + 1];

GetModuleFileName(NULL, szModule, MAX_PATH);

int cArgs = 2;

char *pArg[2] = {szModule, W2A(bstrTarget));

//

//Создать набор оконечных точек, который будет возвращен

//этим методом

//

CComObject<CEndpointCollection> *pResult; CComObject<CEndpointCollection>::CreateInstance(&pResult); pResult->AddRef();

//

//Подготовить указатель на контекст вызова и сохранить его

//в локальной памяти потока

//

PTOOL_CALL_CONTEXT pCtx = new TOOL_CALL_CONTEXT; pCtx->pIFaceVector = &pResult->m_coll;

TlsSetValue(g_dwCOMCallTls, (PVOID)pCtx);

BEGIN_ENTRYPOINT(); rcpdump_main(cArgs, pArg); END_ENTRYPOINT();

// Вызов завершен, его контекст нам больше не нужен delete pCtx;

51// Присвоить указатель на полученный набор аргументу ppResult

52*ppResult = pResult;

53

54}

55};

Анализ

К этому моменту строки 1–7 уже должны быть вам привычны, это объявление ATL-атрибута, в котором говорится, что далее следует класс компонента со следующими характеристиками:

компонент должен работать только в модели с раздельными потоками;

его не зависящий от версии PROGID равен «RPCDump.Scanner», следовательно для обращения к нему можно написать что-то типа var

rpcdump = new ActiveXObject(«RPCDump.Scanner»);

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

 

F

 

 

 

 

 

 

 

t

 

 

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

 

r

 

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

 

to

 

 

694 Глава 13. Написание компонентов для задач, связанных с безопасностью

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

 

 

w

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

 

 

.

 

 

 

 

g

.c

 

 

 

 

 

p

 

-xcha

 

 

 

 

номер версии кокласса 1.0;

 

 

 

df

 

e

 

 

 

 

 

 

n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

его CLSID равен {8B680433-A2BE-491E-B2CF-F858C1C16A93}.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Как и в объявлениях всех предыдущих коклассов, здесь присутствует директива компилятора ATL_NO_VTABLE, и он наследует классу IDispatchImpl, который, в свою очередь, является производным от класса IRpcEnum, реализованного компонентом.

Âинтерфейсе IRpcEnum имеется единственный метод Execute, который и занимает большую часть кода в строках 12–55.

Метод Execute принимает два аргумента, один из которых служит для возврата значения. Первый аргумент – это адрес машины, на которой нужно просканировать оконечные точки RPC. С помощью второго возвращается результат сканирования в виде указателя на интерфейс набора, содержащего интерфейсы IEndPoint.

Основное назначение этого метода – создать среду для исполнения исходной программы, получить собранные данные с помощью процедур интеграции и представить их в виде набора. Рассмотрим подробно, как это делается.

Âстроках 14–16 проверяется корректность переданных методу Execute аргументов. Это следует делать для всех COM-интерфейсов.

Âстроках 20–25 задаются аргументы argc è argv, которые ожидает функция rpcdump_main. Массив argv строится следующим образом:

[0]Путь к модулю, например: "C:\\rpcdump.exe"

[1]Имя целевого хоста, например: "john"

Коль скоро задано два аргумента и это отражено в argc, функция rpcdump_ main будет довольна.

Âстроках 31–33 создается объект набора, который будет возвращен рассматриваемым методом. Обратите внимание, что член m_coll, унаследованный от ICollectionOnSTLImpl, используется также в роли указателя на вектор,

âкотором хранятся данные обо всех RPC-интерфейсах. Это становится оче- видным из строки 40, в которой m_coll присваивается указатель на структуру

TOOL_CALL_CONTEXT.

Âстроке 39 из кучи выделяется память для структуры TOOL_CALL_ CONTEXT, а в строке 42 указатель на нее сохраняется в локальной памяти потока. В этой структуре будут храниться данные, полученные от процедур интеграции. Если вспомнить код этих процедур, то это утверждение станет более понятным:

PTOOL_CALL_CONTEXT pCtx=(PTOOL_CALL_CONTEXT)TlsSetValue(g_dwCOMCallTls);

В строках 44–46 вызывается функция rpcdump_main. Здесь используются макросы BEGIN_ENTRYPOINT() и END_ENTRYPOINT(), о которых мы го-

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

Добавление СОМ расширений в программу RPCDUMP 695

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

 

.c

 

 

.

 

-x cha

 

 

.c

 

 

 

p

 

-xchворилиa

выше. Функции rpcdump_main передаются подготовленные в строках

 

g

 

 

 

 

 

 

 

 

 

g

 

 

 

 

 

p

 

 

 

 

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

20–25 аргументы argc è argv.

Последний шаг – почистить за собой и вернуть результат клиенту. В строке 49 освобождается память, выделенная для структуры TOOL_CALL_CONTEXT, а в строке 52 выходному аргументу ppResult присваивается указатель на набор.

Интеграция с приложением: файл COMSupport.h

А теперь посмотрим, что нужно изменить в исходном файле rpcdump.c, чтобы процедуры интеграции могли получить от него нужную информацию.

В примере 13.9 приведен полный код файла COMSupport.h.

Пример 13.9. Файл COMSupport.h

1// Вместо выхода возбуждаем исключение, которое можно перехватить

2 #define exit(x) *((unsigned long*) 0) = 0; // нарушение защиты

3

4void SetInterfaceID(char *pIFaceID);

5void SetVersion(char *pVersion);

6void SetUUID(char *pUuid);

7void SetBinding(char *pBinding);

8void NextRecord();

Анализ

Неочевидна только строка 2. Показанный в ней макрос переопределяет функцию exit. В результате всюду, где эта функция встретится в тексте программы, она будет заменена значением макроса, что приведет к исключению в результате нарушения защиты памяти. Это нужно по следующим причинам:

когда происходит обращение к методу IRpcEnum::Execute, он вызывает функцию rpcdump_main, а та в свою очередь – функцию exit. При этом EXE-сервер COM завершается, а клиент при этом получает не ожидаемую информацию, а код ошибки. Ясно, что такое поведение нежелательно;

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

использование макросов BEGIN_ENTRYPOINT() и END_ENTRYPOINT() в сочетании с переопределение символа exit – это элегантное и удобное решение.

В строках 4–8 объявляются внешние процедуры интеграции с приложением.

Интеграция с приложением: файл RPCDump.c

Теперь посмотрим, что надо изменить в файле RPCDump.c. В примере 13.10 приведено несколько фрагментов из этого файла.

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

696 Глава 13. Написание компонентов для задач, связанных с безопасностью

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

-xcha

 

 

.c

 

 

 

p

 

 

 

Пример 13.10. Фрагменты файла RPCDump.c, имеющие отношение

 

 

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

к интеграции с COM

1#include <windows.h>

2 #include <winnt.h>

3

4 #include <stdio.h>

5

6#include <rpc.h>

7 #include <rpcdce.h>

8

9#include "COMSupport.h"

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Анализ

В строке 9 включается рассмотренный выше заголовочный файл COMSupport.h. Обратите внимание, что он включается последним.

1 rpcErr=RpcMgmtEpEltInqNext (hInq, &IfId, &hEnumBind, &uuid, &pAnnot);

2 if (rpcErr == RPC_S_OK) {

3unsigned char *str = NULL;

4unsigned char *pincName = NULL;

5

numFound++;

6

 

7//

8// Напечатать IfId

9//

10if (UuidToString (&IfId.Uuid, &str) == RPC_S_OK) {

11char szVersion[50];

12printf("IfId: %s version %s.%d\n", str, IfId.VersMajor,

13IfId.VersMinor);

14

15 sprintf(szVersion, "%d.%d", IfId.VersMajor, IfId.VersMinor);

16

17// Код для поддержки COM

18SetVersion(szVersion);

19SetInterfaceID((char*)str);

20// —

21

22RpcStringFree (&str);

23}

Âэтом фрагменте мы получаем идентификатор и номер версии RPC-ин- терфейса, а затем передаем их соответствующим процедурам интеграции с приложением в строках 18 и 19.

1//

2 // Напечатать ID объекта

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

d

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

Добавление СОМ расширений в программу RPCDUMP 697

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

 

 

 

 

 

 

 

 

p

 

 

 

 

 

 

 

 

 

 

 

 

 

 

e

 

 

 

 

df-x chan

e

 

 

 

 

df-xchan3

 

//

 

 

 

 

 

 

 

 

 

 

 

 

 

4 if (UuidToString(&uuid, &str) == RPC_S_OK) {

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5

 

 

 

printf("UUID: %s\n", str);

 

 

 

 

 

 

 

 

 

 

 

6

7 SetUUID((char*)str);

8

9RpcStringFree (&str);

10}

Âэтом фрагменте мы получаем идентификатор объекта и передаем его процедуре интеграции с приложением в строке 7.

1 //

2 // Напечатать привязку

3 //

4 if (RpcBindingToString(hEnumBind, &str) == RPC_S_OK) {

5 printf("Binding: %s\n", str);

6

7 SetBinding((char*)str);

8

9 RpcStringFree (&str);

10 }

Здесь мы получаем строку привязки RPC и передаем ее процедуре интеграции с приложением SetBinding в строке 7.

1 NextRecord();

2}

3while (rpcErr != RPC_X_NO_MORE_ENTRIES);

После того как все относящиеся к одному интерфейсу данные получены и переданы процедурам интеграции, RPCDump вызывает функцию NextRecord, которая сохраняет данные во внутренней структуре и готовится к приему следующей порции.

1int

2 rpc_dum_main(int argc, char *argv[])

3{

4// код опущен

5}

Это определение точки входа в программу RPCDump. Раньше она, конеч- но, называлась main, нам пришлось ее переименовать, чтобы при входе мы попадали в функцию, необходимую для поддержки COM.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

698 Глава 13. Написание компонентов для задач, связанных с безопасностью

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

 

e

 

 

 

 

 

 

n

Резюме

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Модель компонентных объектов (COM) – это спецификация, позволяющая совместно работать различным частям программного обеспечения. Вот некоторые из достоинств технологии COM, делающие ее удобной для использования в программах, так или иначе связанных с информационной безопасностью.

Независимость от языка. К интерфейсам COM объектов можно полу- чить доступ из любого языка, поддерживающего двоичную спецификацию COM. К числу таких языков относятся C, C++, C#, Visual Basic, JScript, Perl и Python, хотя этот перечень, конечно, не исчерпывающий. Таким образом, COM-объект, написанный, к примеру, на Visual Basic, можно вызвать из программы на C++ и наоборот.

Контекст исполнения. COM обеспечивает отделение интерфейса от реализации в самом что ни на есть буквальном смысле. COM-объект, к которому обращается приложение, может находиться в трех местах: внутри адресного пространства клиента, в адресном пространстве другого приложения и на удаленном сервере.

Интерпретируемые языки. СOM-объект, который поддерживает специальный интерфейс IDispatch, можно вызывать из таких интерпретируемых языков, как VBScript и JScript. Следовательно, такие COMобъекты можно создавать, в частности, из браузера Internet Explorer или из программы Windows Scripting Host.

Применение библиотеки Active Template Library (ATL) – это лучший способ программирования COM-объектов на языке C++. При этом объем вспомогательного кода, необходимого для поддержки спецификации COM, сводится к минимуму и, в отличие других способов, например, MFC, компоненты получаются очень эффективными и компактными.

Обзор изложенного материала

Модель COM

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

Все объекты, соответствующие спецификации COM, должны реализовывать интерфейс IUnknown, в котором есть три метода: QueryInterface,

AddRef è Release.

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

ATL

 

.

 

 

 

 

 

.c

 

 

 

p

 

-xchБиблиотекаa

 

 

 

 

 

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Часто задаваемые вопросы 699

 

to

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

ATL – это высокоэффективная библиотека шаблонов, предназначенная для реализация COM-объектов на языке C++.

В Visual Studio .NET в библиотеку ATL включена поддержка атрибутов.

Добавление COM-расширений в программу RPCDUMP

Добавление COM-расширений в существующую программу делает возможным доступ к ее функциональности из других языков и контекстов исполнения.

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

Ссылки на сайты

www.applicationdefense.com. На сайте Application Defense имеется большая подборка бесплатных инструментов по обеспечению безопасности в дополнение к программам, представленным в этой книге.

http://msdn.microsoft.com. Сайт Microsoft Developer Network предоставляет в распоряжение разработчиков, пишущих для операционных систем Microsoft, огромный объем информации, в том числе по технологиям COM и ATL.

http://msdn.microsoft.com/vstudio. Эта ссылка ведет на раздел сайта, посвященный среде разработки Microsoft – Visual Studio .NET.

http://www.bindview.com/support/Razor/Utilities. Страница сайта компании BindView, посвященная инструментарию для обеспечения безопасности, разработанному группой RAZOR. Программа RPCDump создана именно этой группой.

Часто задаваемые вопросы

Следующие часто задаваемые вопросы, на которые отвечают авторы книги, призваны помочь вам оценить, насколько хорошо вы поняли идеи, изложенные в данной главе, и возможные их применения на практике. Если вы хотите задать авторам вопрос, зайдите на страницу www.syngress.com/solutions и заполните форму Ask the Author. Заодно вы получите доступ к тысячам других FAQов на сайте ITFAQnet.com.

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

700 Глава 13. Написание компонентов для задач, связанных с безопасностью

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

 

 

 

 

 

 

 

m

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

-xcha

 

 

 

Â: Где можно получить дополнительную

 

 

 

p

 

 

 

 

 

 

 

 

 

 

 

 

e

 

информацию о технологиях-x cha

 

e

 

 

 

 

df

 

 

n

 

 

 

 

 

 

df

 

 

n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

COM è ATL?

Î: В сети Интернет есть множество ресурсов, содержащих вполне прилич- ное введение в COM. Лучшим из них, конечно, является сайт Microsoft. Загляните на страницы www.microsoft.com/com è msdn.microsoft.com. Хорошее введение в основы технологии COM можно найти в книге Dale Rogerson «Inside COM» (Microsoft Press, 1996). О библиотеке ATL можно узнать на сайте MSDN, а также из книги George Shepherd, Brad King «Inside ATL».

Â: Что такое ATL-атрибуты?

Î: Программирование с использованием атрибутов – это новая возможность, появившаяся в Visual Studio .NET. Она позволяет заметно сократить время разработки за счет того, что написание стандартного вспомогательного кода поручается компилятору и провайдерам атрибутов. Если в тексте встречается некий атрибут, то на этапе компиляции в вашу программу вставляется код, реализующий функции этого атрибута. Например, если используется атрибут [module(dll)], то будет вставлен код вашего модуля, в котором уже реализованы четыре требуемых COM функции: DllGetClassObject, DllCanUnloadNow, DllRegisterServer и DllUnregisterServer.

Â: Для чего нужен макрос препроцессора _ATL_ATTRIBUTES?

Î: Он включает поддержку ATL-атрибутов. Если забыть про него и воспользоваться атрибутами, то результат может оказаться неожиданным.

Â: Я понимаю, как макросы BEGIN_ENTRYPOINT и END_ENTRYPOINT помогают перехватить поток управления, но как получить значение аргумента, переданного функции, когда возбуждается исключение?

Î: Чтобы ответить на этот вопрос, имеет смысл посмотреть, во что расширяются макросы BEGIN_ENTRYPOINT и END_ENTRYPOINT:

#define BEGIN_ENTRYPOINT() __try { #define END_ENTRYPOINT() } \ __except(EXCEPTION_EXECUTE_HANDLER) {}

А вот как выглядит переопределение символа exit(n):

#define exit(x) *((unsigned long*) 0) = 0;

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