Взлом приватных данных с помощью c++

Пояснение: этот вопрос изначально возник из-за проблемы, которую я придумал, и не связан с программированием для реальных систем.

Предположим, у меня есть класс, и я знаю его архитектуру, которую я не могу изменить, и я не хочу его наследовать, но я хочу получить доступ к его закрытым данным и функциям. Как мне это сделать?

Предположим, мой класс выглядит так:

class A {
public:
    int v = 89;

private:
    int a = 5;
    virtual void function(int a, int b) {
        cout << a << " " << b << endl;
    }
};

person CoralK    schedule 27.07.2018    source источник
comment
Единственным правильным ответом было бы не делать это, а вместо этого сделать звук и правильный дизайн, который не требует трудных для чтения, понимания и поддержки хаков. Особенно потому, что подобные хаки нарушат ряд или правила (например, строгое правило псевдонимов и т. п.) и, скорее всего, приведет к неопределенному поведению. Это также очень зависит от реализации, и даже изменение версии компилятора или аппаратной платформы может привести к тому, что хак больше не будет работать.   -  person Some programmer dude    schedule 27.07.2018
comment
@Someprogrammerdude даже более вероятно: изменение уровней оптимизации или встраивание событий. Это может работать нормально, но вызов функции мешает, и он загорается.   -  person Quentin    schedule 27.07.2018
comment
#define private public перед включением этого файла   -  person alter igel    schedule 27.07.2018
comment
@alterigel нет, все еще UB.   -  person Quentin    schedule 27.07.2018
comment
Зачем задавать вопрос, а потом отвечать на него самому? Кроме того... ваша функциональная функция имеет параметр "a", который скрывает приватную переменную с тем же именем.   -  person Tim Randall    schedule 27.07.2018
comment
@TimRandall самостоятельный ответ вполне приемлем.   -  person Passer By    schedule 27.07.2018
comment
@TimRandall, это действительно поощряется! Цель SO — принести пользу будущим исследователям, столкнувшимся с похожими проблемами.   -  person Quentin    schedule 27.07.2018
comment
Спасибо за информацию. Извиняюсь за публикацию моего комментария до того, как он был закончен (я не ожидал, что клавиша Enter сделает это).   -  person Tim Randall    schedule 27.07.2018
comment
@TimRandall Кроме того ... ваша функциональная функция имеет параметр «a», который скрывает частную переменную с тем же именем - я знаю, что моей целью была идея, как получить доступ к функции, так что это не имеет значения для моей проблемы.   -  person CoralK    schedule 27.07.2018
comment
Я думаю, что то, что вы пытаетесь предложить, ломает идею инкапсуляции данных. Насколько я знаю, нет безопасного правильного способа сделать это без A: изменения оригинала, в котором вы заявили, что не можете, или с использованием какой-либо формы интерпретации, которая может и, вероятно, приведет к UB, что никогда не будет хорошо.   -  person Francis Cugler    schedule 27.07.2018


Ответы (2)


некоторое время назад наткнулся на аккуратный трюк с шаблоном, чтобы сделать это в этом блоге: http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html

НЕ используйте это ни в каком производственном коде, это просто образовательный пример!!!

в основном он использует рычаг «частного», который игнорируется в какой-то части инициализации шаблона.

template<typename Tag>
struct result {
    /* export it ... */
    typedef typename Tag::type type;
    static type ptr;
};

template<typename Tag>
typename result<Tag>::type result<Tag>::ptr;

template<typename Tag, typename Tag::type p>
struct rob : result<Tag> {
    /* fill it ... */
    struct filler {
        filler() { result<Tag>::ptr = p; }
    };
    static filler filler_obj;
};

template<typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;

использование: возьмите следующую структуру:

struct A {
private:
    void f() {
        std::cout << "proof!" << std::endl;
    }
};

создай своего "разбойника"

struct Af { typedef void(A::*type)(); };
template class rob<Af, &A::f>;

используй это:

int main()
{
    A a;
    (a.*result<Af>::ptr)();

    return 0;
}
person skeller    schedule 27.07.2018

Менее рискованным способом будет сделать вашу функцию/класс friend класса, если вам разрешено изменять только заголовочный файл.

// Add
class HackA;

class A {
public:

    // Add
    friend class HackA;

    int v = 89;

private:
    int a = 5;
    virtual void function(int a, int b) {
        cout << a << " " << b << endl;
    }
};

Теперь вы можете использовать:

class HackA {
public:
    int number(A const& a) { return a.v; }
    int another_number(A const& a) { return a.a; }
    void target_function(A& a, int number, int another_one)
    {
       a.function(number, another_one);
    }
};

int main()
{
    A a;
    HackA hacker

    cout << hacker.number(a) << " " << hacker.another_number(a) << endl;
    hacker.target_function(a, 9, 3);

    return 0;
}
person R Sahu    schedule 27.07.2018
comment
Как я уже упоминал, этот вопрос относится к случаю, когда вы не можете редактировать целевой класс. Если вы можете редактировать этот класс, просто добавьте геттеры и сеттеры. - person CoralK; 27.07.2018
comment
@KorelK, я ничего не заметил в вашем сообщении о невозможности изменить файл .h. - person R Sahu; 27.07.2018
comment
Предположим, у меня есть класс, и я знаю его архитектуру, которую я не могу изменить. - person CoralK; 27.07.2018
comment
@KorelK, понятно. Я прочитал это совсем по-другому - я прочитал, что это означает, что вы не можете добавлять/удалять/изменять переменные-члены или функции-члены. - person R Sahu; 27.07.2018
comment
Если вам разрешено изменять файл заголовка, что мешает кому-либо добавить общедоступное определение для геттера int getA() { return a; } в заголовок? - person Killzone Kid; 27.07.2018
comment
@KillzoneKid, это менее рискованно, потому что вы не изменяете интерфейс/реализацию класса. - person R Sahu; 27.07.2018