Заранее извиняюсь, если тема не нова - поиском не нашел ничего... Так вот...когда-то давно слышал, что используя ассемблерные хитрости, можно получить доступ к приватным и защищенным членам класса. Так ли это? И, если идея реализуема, то как это делается? Буду благодарен за любую информацию или ссылки.
Код (Text): class my_class { public: int a,b,c; protected: int x,y,z; }; тоже самое на асме можно записать так: Код (Text): my_class struct a dd ? b dd ? c dd ? z dd ? y dd ? z dd ? my_class ends предположим, что регистр EBX указывает на экземпляр класса my_class, тогда получить доступ к переменной y можно так: Код (Text): mov eax,dword ptr[ebx+16]
Код (Text): class my_class { public: int a,b,c; protected: virtual int method0(int a); virtual void method1(); }; тоже самое на асме можно записать так: Код (Text): my_class struct a dd ? b dd ? c dd ? pvtbl dd ? my_class ends предположим, что регистр EBX указывает на экземпляр класса my_class, тогда получить указатель на функцию method1 можно так: Код (Text): mov eax,dword ptr[ebx+12] mov eax,dword ptr[eax+4] ;; в EAX - указатель на method1() вроде так, точно не уверен. Added: pvtbl - указатель на адреса виртуальных функций
Неужели все настолько просто!? Получается, что в рантайме приватные данные программно никак не защищены и нелегальные обращения к ним отсекаются только при компиляции? вот блин....
Ессно. Так же как и в Си - понятие "struct" существует только во время компиляции. Компилятор выплёвывает инструкции по чтению и записи памяти. С++ добавляет дополнительные абстракции но это всё компилится всегда в натив и работает на голом силиконе. (при условии что ты не вызываешь внешние библиотеки). Такова архитектура Си и С++, т.е. это не случайно.
Так, хорошо...Тогда еще вопрос: а если в классе есть невиртуальные методы, то как объект будет выглядеть на асме? Пример: class MyClass { private: int a; int b; void func1(); void func2(); }; как будет выглядеть выделенная под объект память в том месте, где func1 и func2? там будут указатели на методы, реализации которых расположены где-то в другом месте? или же какой нибудь jmp на метод?
babandr Также, как и обычная ф-ия. Только в нее еще будет передаваться this. Компилятор MS кладет его в ecx, gcc, насколько я помню, передает его через стек. Код func1 & func2 будет жить со всем остальным кодом, они никак не связаны с самим объектом. При выполнении они получат его адрес либо в ecx либо в стеке.
Mika0x65, ты меня не понял... Я спрашивал не о том, как будет выглядеть реализация ф-ции, а что будет на ее месте в выделенной под экземпляр памяти. если следовать логике первых ответов в этой теме, то объект на асме будет выглядеть примерно так: MyClass struct a DWORD ? b DWORD ? ;далее место методов ; и как это будет выглядеть? ; ends
Код методов не лежит рядом с членами класса. Данные объекта лежат либо в стеке (автоматический объект), либо в куче (динамический объект). А код методов живет в секции кода и получает адрес объекта, с которым он работает. Т.е. будет примерно так: struct AnyStruct a dd ? b dd ? ends И где-нибудь код: i_am_method: push ebp mov ebp, esp mov dword [ecx], 0x1 mov dword [ecx + 0x4], 0x2 pop ebp ret Это примерно тоже самое что и: class AnyStruct { int a; int b; void i_am_method() {a = 1; b = 2;} }
Но какие-либо признаки наличия методов должны же быть у экземпляра! А получается, что в данном случае их просто нету...как такое может быть?
Признаков нет. Если метод виртуальный, то он будет в таблице виртуальных ф-ий. Таблица живет где-нибудь в памяти, ее адрес хранится в самом объекте, как член класса. Тогда вызов ф-ии выглядит, например, так: just_a_code: mov ecx, [address_of_an_object] mov eax, [ecx] push some_param call [eax + 0x8] ;вызов второй по индексу виртуальной ф-ии. Т.е. объект -- это просто кусочек данных в памяти.
babandr Нет, т.к. в скомпилированном коде они не нужны. Правда в борландовской VCL-ной модели классов есть еще понятие published (опубликованных) методов и полей, адреса которых можно определить по имени (юзаются инспектором объектов при проектировании форм) и соотв-но их имена и адреса хранятся в отдельных таблицах, а ссылки на эти таблице прицеплены к vmt по фикс.отрицательным смещениям
Эээ...если -невиртуальные методы класса хранятся отдельно -в экземпляре нет информации об их наличии/отсутствии -при их наличии у экземпляре нет информации о месте их расположения в коде, то получается, что получить доступ к этим методам никак нельзя, так?
Смотря что считать доступом к ним. Вызвать, например, их можно запросто. А вот найти чуть сложнее -- это надо код руками просматривать и искать, куда объект передается как this. Это и будут методы. Правда, в статические методы this не передается, их найти сложнее.
babandr Тут такая же ситуация как и с константами. Компилятор генерит код call 0x040AA555 , ведь адрес ф-ии это в некоторой степени константа.