COM

Oct 22, 2010 17:22

Много раз я слышал не самые лестные отклики о данной технологии. Чаще всего описание его "тормознутости". Сегодня решил проверить все сам. Посмотрим...


Подопытный

Стыд мне и позор, но его я спер где-то на просторах тырнета. Сейчас выложить не могу ибо лень выкладывать где-то, вставлять сцылы и.т.д.
В общем это dll и клиент к ней. Написано без использования ATL(за него я еще не брался. Может он правда глючный и этим объясняются нападения на вполне адекватную технологию ?)

Трепанация...

Проверим интерфейс ICreateCar.

Интерфейс объявлен так:

DECLARE_INTERFACE_(ICreateCar, IUnknown)
{
     STDMETHOD(SetPetName)(BSTR petName) PURE;
     STDMETHOD(SetMaxSpeed)(int maxSp) PURE;
};

Согласно спецификации первыми идут QueryInterface(смещение 0), AddRef(смещение 4) и Release(смещение 8).
SetPetName следует за Release, т.е. 8+sizeof(DWORD) = 0C
SetMaxSpeed соответственно 0c+4=10;

итак:

Перед началом работы следует вызвать CoGetClassObject:
hr = CoGetClassObject(CLSID_CoCar, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void**)&pCF);

LEA EAX,[LOCAL.6]; -(&pICar)----------------------
PUSH EAX ; 0012ff50
PUSH OFFSET CoCarClient.00417924
PUSH 0
PUSH 1
PUSH OFFSET CoCarClient.004178E8
CALL DWORD PTR DS:[<&ole32.CoGetClassObject>]; hr = CoGetClassObject(CLSID_CoCar, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void**)&pCF);

возвращает 00BB21D0 в LOCAL.6 (адрес 0012ff50)

Далее получение указателя:
hr = pCF->CreateInstance(NULL, IID_ICreateCar, (void **)&pICreateCar);

asm
LEA EAX,[LOCAL.9]; --------------------------
PUSH EAX ; 0012ff44
PUSH OFFSET CoCarClient.004178D4 ; 004178D4
PUSH 0
MOV ECX,DWORD PTR SS:[LOCAL.6] ; 00bb21d0 (!!!)
MOV EDX,DWORD PTR DS:[ECX] ; 00da4c70
MOV EAX,DWORD PTR SS:[LOCAL.6] ; 00bb21d0 (!!!)
PUSH EAX
MOV ECX,DWORD PTR DS:[EDX+0C] ; 00d4c0ef
CALL ECX ; hr = pCF->CreateInstance(NULL, IID_ICreateCar, (void **)&pICreateCar);

возвращает 00bb221c в LOCAL.9(адрес 0012ff44)

Собцтвенно пользуемся :

PUSH 1E ; --------------
MOV EAX,DWORD PTR SS:[LOCAL.9] ; 00BB221C (!!!)
MOV ECX,DWORD PTR DS:[EAX] ; 00da4c10
MOV EDX,DWORD PTR SS:[LOCAL.9] ; 00bb221c (!!!)
PUSH EDX
MOV EAX,DWORD PTR DS:[ECX+10] ; 00d4bbf9
CALL EAX ; pICreateCar->SetMaxSpeed(30);

ECX+10 - SetMaxSpeed. 10 - константа установленная на этапе компиляции. Никаких затрат на поиск функции.

(для маньяков - идем дальше)

00D4BBF9 JMP CarInProcServer.00D4E450

->и сразу нужный код:

00D4E450 PUSH EBP
00D4E451 MOV EBP,ESP
00D4E453 SUB ESP,0C0
00D4E459 PUSH EBX
00D4E45A PUSH ESI
00D4E45B PUSH EDI
00D4E45C LEA EDI,[EBP-0C0]
00D4E462 MOV ECX,30
00D4E467 MOV EAX,CCCCCCCC
00D4E46C REP STOS DWORD PTR ES:[EDI]
00D4E46E CMP DWORD PTR SS:[EBP+0C],1F4
00D4E475 JGE SHORT CarInProcServer.00D4E480
00D4E477 MOV EAX,DWORD PTR SS:[EBP+8]
00D4E47A MOV ECX,DWORD PTR SS:[EBP+0C]
00D4E47D MOV DWORD PTR DS:[EAX+10],ECX
00D4E480 XOR EAX,EAX
00D4E482 POP EDI
00D4E483 POP ESI
00D4E484 POP EBX
00D4E488 RETN 8

ВСЕ !!!

Еще пользуемся

PUSH EAX ; ------------------------------
MOV ECX,DWORD PTR SS:[LOCAL.9] ; 00bb221c
MOV EDX,DWORD PTR DS:[ECX] ; 00da4c10
MOV EAX,DWORD PTR SS:[LOCAL.9] ; 00bb221c
PUSH EAX
MOV ECX,DWORD PTR DS:[EDX+0C] ; 00d4b672
CALL ECX ; pICreateCar->SetPetName(PetName);

EDX+0C - SetPetName. Все просто...

PUSH OFFSET CoCarClient.004178C0 ; ----------------------------------
MOV ECX,DWORD PTR SS:[LOCAL.9] ; 00bb221c
MOV EDX,DWORD PTR DS:[ECX] ; 00da4c10
MOV EAX,DWORD PTR SS:[LOCAL.9] ; 00bb221c
PUSH EAX
MOV ECX,DWORD PTR DS:[EDX] ; 00d4bbd6
CALL ECX ; hr = pICreateCar->QueryInterface(IID_IStats, (void **)&pIStats);

получаем 00BB2218, указатель на IStats(с ним все точно так же)
EDX просто(прибавлять 0 глупо просто :) )- первый метод: QueryInterface.

MOV DWORD PTR SS:[LOCAL.3],EAX ; -------------------------------------
MOV EAX,DWORD PTR SS:[LOCAL.9] ; 00bb221c
MOV ECX,DWORD PTR DS:[EAX] ; 00da4c10
MOV ESI,ESP
MOV EDX,DWORD PTR SS:[LOCAL.9] ; 00bb221c
PUSH EDX
MOV EAX,DWORD PTR DS:[ECX+8] ; 00d4b596
CALL EAX ; pICreateCar->Release();

ECX+8 - Release стоит третьим.

И где тормоза ?

Для сравнения используя GetProcAddress кода будет больше в разы. Вычисляется смещение экспорта, куча проверок, производится поиск, причем ординалами пользуются далеко не всегда, чаще поиск производится по ТЕКСТУ.
(сравните с GUID).
Скоро попробую ATL... может там ? Поддержка совместимости с любым языком ? Маршаллинг ? Защита ? Хм...

Даже после беглого анализа видно множество проблем в стиле "а что если я злоумышленник, возьму и подменю либу/гуид...". Хм. Ответ очевиден: access violation или... кто знает :)

Пора браться за ATL. Не могу поверить что подобные проблемы имеют место быть. Хотя, зная Мелкософт...

reverse engeneering, it, c++

Previous post Next post
Up