
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.80.4.147] |
![]() |
|
Сообщ.
#1
,
|
|
|
Приветствую!
Как-то недавно где-то на форуме поднималась сабжевая тема. Захотелось поэксперементировать, вызвать напрямую, и таки получилось. Скажу сразу что реализация - есть хак. Иными словами, некоторые компиляторы могут собрать неработающий код. Вощем, опубликую чтобы было ![]() Онлайн выполнение тут. ![]() ![]() #include <iostream> // ----------------------------------------- class Base { public: virtual ~Base(){} private: virtual void ShowBase() { std::cout << "BaseShow" << std::endl; } }; // ----------------------------------------- class Derived: public Base { public: virtual void ShowDerived() { std::cout << "DerivedShow" << std::endl; } }; // ----------------------------------------- #ifdef _MSC_VER #define IDX 1 #else #define IDX 2 #endif int main() { Derived *D = new Derived(); (*(void(*)(void*))((void**)(*(void**)D))[IDX])(D); delete D; return 0; } |
Сообщ.
#2
,
|
|
|
Т.е. вызывался приватный метод?
Какая прелесть. |
Сообщ.
#3
,
|
|
|
Ой, делов-то:
![]() ![]() #define private public #include "BaseClass.h" ![]() |
Сообщ.
#4
,
|
|
|
Pacific, задача была вызвать приватный метод, а не делать его пабликом.
|
Сообщ.
#5
,
|
|
|
На стековерфлове предложили еще один вариант:
![]() ![]() #include <iostream> class Private { void private_func() { std::cout << "Pwned!" << std::endl; } }; class DerivedPrivate : public Private { }; using PTR = void (Private::*)(); PTR ptr; template <PTR ptr> struct Exploit { static struct D { D() { ::ptr = ptr; } } d; }; template <PTR ptr> typename Exploit<ptr>::D Exploit<ptr>::d; template struct Exploit<&DerivedPrivate::private_func>; int main() { (DerivedPrivate().*ptr)(); } |
Сообщ.
#6
,
|
|
|
DELETED
Сначала, не подумав, решил, что достаточно сделать ![]() ![]() static_cast<Base*>(this) ![]() Не, без тяжелых извращений к приватным членам класса доступ не получить. И не надо! |
![]() |
Сообщ.
#7
,
|
|
JoeUser, чему ты удивляешься-то? Тому, что при наличии указателя на что-то можно с чем-то делать всё, минуя любые охранные средства языка? Дык не составляет труда получить доступ и к приватным мемберам. Я даже как-то код писал, который в ран-тайм распарсивает структуру с битовыми полями и составляет словарь из битовых смещений от начала и длин каждого такого поля. Это требовалось для тестового движка одного из проектов.
Структура VMT не стандартизирована, даже её наличия не требуется. Твой код написан под конкретную 32-битную реализацию – кстати, какую? – и нет никаких гарантий, что будет работать в других. Код со СтэкОверфлоу не страдает этим недостатком, но страдает другим: он не должен компилиться. Добавлено Но я могу предложить другой способ. ![]() ![]() #include <iostream> class Private { void private_func() { std::cout << "Pwned!" << std::endl; } public: template <typename T> void f(); }; /* ... */ class X {}; void (Private::*ptr)(); template <> void Private::f<X>() { ptr = &Private::private_func; } int main() { Private().f<X>(); (Private().*ptr)(); } |
Сообщ.
#8
,
|
|
|
Цитата Qraizer @ Твой код написан под конкретную 32-битную реализацию – кстати, какую? Это почему? Цитата Qraizer @ Но я могу предложить другой способ. "Легальные" способы, в случае перегрузки, вызовут перегруженный метод, а не базового класса. А в твоем варианте как с этим? |
Сообщ.
#9
,
|
|
|
Цитата Qraizer @ 32-битную реализацию – кстати, какую? Собирал на FreeBSD 11.0 x64 - полет нормальный. Цитата uname -a FreeBSD freebsd-11.0 11.0-RELEASE-p1 FreeBSD 11.0-RELEASE-p1 #1: Tue Oct 11 13:50:48 MSK 2016 majestio@freebsd-11.0:/usr/obj/usr/src/sys/MYKERNEL amd64 |
![]() |
Сообщ.
#10
,
|
|
Цитата JoeUser @ Уже нет, uint32_t* заменил на void**.Это почему? Цитата JoeUser @ Мой строго стандартен. А в твоем варианте как с этим? |