Can I access private members outside the classroom without using friends?

Renouncement

Yes, I am fully aware that what I ask is absolutely stupid and that anyone who would like to try such a thing in production code should be fired and / or removed. I am mostly looking to see if it can be done.

Now, if this is not the case, is there a way to access private members of a class in C ++ from outside the class? For example, is there a way to do this with pointer offsets?

(welcome naive and other technologies that are not ready for production)

Update

As noted in the comments, I asked this question because I wanted to write a blog post about excessive encapsulation (and how it affected TDD). I wanted to see if there is a way to say: "Using private variables is not a 100% reliable way to force encapsulation, even in C ++." In the end, I decided to focus more on how to solve the problem, rather than why it was the problem, so I did not use some of the things that were raised here, just as I planned, but I still left a link.

In any case, if anyone is interested in how this happened, here it is: Enemies of the tested development Part I: encapsulation (I suggest reading it before deciding that I'm crazy).

+53
c ++ private-members encapsulation
Jan 08 '09 at 12:45
source share
23 answers

If the class contains any member functions, you can customize this member function to suit your needs. Even if the original developer did not think about it.

safe.h

class safe { int money; public: safe() : money(1000000) { } template <typename T> void backdoor() { // Do some stuff. } }; 

main.cpp:

 #include <safe.h> #include <iostream> class key; template <> void safe::backdoor<key>() { // My specialization. money -= 100000; std::cout << money << "\n"; } int main() { safe s; s.backdoor<key>(); s.backdoor<key>(); } 

Output:

 900000 800000 
+62
Jan 08 '09 at 16:43
source share

I added an entry to my blog (see below) that shows how this can be done. Below is an example of how you use it for the next class

 struct A { private: int member; }; 

Just declare a structure for it, where you describe it, and instantiate the implementation class used to rob

 // tag used to access A::member struct A_member { typedef int A::*type; friend type get(A_member); }; template struct Rob<A_member, &A::member>; int main() { A a; a.*get(A_member()) = 42; // write 42 to it std::cout << "proof: " << a.*get(A_member()) << std::endl; } 

The Rob class template is defined this way, and it needs to be defined only once, regardless of how many private members you plan to get

 template<typename Tag, typename Tag::type M> struct Rob { friend typename Tag::type get(Tag) { return M; } }; 

However, this does not show that C ++ access rules are unreliable. Language rules are designed to protect against accidental errors - if you try to rob object data, the design language does not take much time to prevent you.

+45
Jul 03 '10 at
source share

The following is hidden, illegal, depending on the compiler and not working depending on various implementation details.

 #define private public #define class struct 

But this is the answer to your OP, in which you explicitly invite a technique that, and I quote, "is absolutely stupid and that anyone who would like to try such a thing in production code should be fired and / or shot."




Another method is to access the private data of the element, by creating pointers using manually encoded / encoded offsets from the beginning of the object.

+28
Jan 08 '09 at 12:53
source share

Hmmm, I don't know if this will work, but it might be worth a try. Create another class with the same layout as an object with private members, but with a private one modified for the public. Create a pointer variable to this class. Use a simple actor to point this to your object with private members and try calling a private function.

Expect sparks and possibly crash;)

+23
Jan 08 '09 at 13:04
source share
 class A { int a; } class B { public: int b; } union { A a; B b; }; 

That should do it.

ETA: It will work for this kind of trivial class, but usually it will not.

TC ++ PL Section C.8.3: "A class with a constructor, destructor, or copy operation cannot be a member type of a union ... because the compiler did not know which member should destroy."

So, we have a better bet: declare class B according to layout A and crack a glance at class privates.

+12
Jan 09 '09 at 3:41
source share

You can definitely access private members with a pointer offset in C ++. Suppose I had the following type definition that I wanted to access.

 class Bar { SomeOtherType _m1; int _m2; }; 

Assuming there are no virtual methods in the bar, a simple case is _m1. Members in C ++ are stored as object location offsets. The first object is at offset 0, the second object is at offset sizeof (first element), etc.

So, here is a way to access _m1.

 SomeOtherType& GetM1(Bar* pBar) { return*(reinterpret_cast<SomeOtherType*>(pBar)); } 

Now _m2 is a little more complicated. We need to move the original sizeof sizeof pointer (SomeOtherType) from the original. Casting to char should ensure that I increase the byte offset

 int& GetM2(Bar* pBar) { char* p = reinterpret_cast<char*>(pBar); p += sizeof(SomeOtherType); return *(reinterpret_cast<int*>(p)); } 
+8
Jan 08 '09 at 15:34
source share

If you can get a pointer to a class member, you can use a pointer no matter what access specifiers (even methods).

 class X; typedef void (X::*METHOD)(int); class X { private: void test(int) {} public: METHOD getMethod() { return &X::test;} }; int main() { X x; METHOD m = x.getMethod(); X y; (y.*m)(5); } 

Of course, my favorite little hack is the back door of my friend’s template.

 class Z { public: template<typename X> void backDoor(X const& p); private: int x; int y; }; 

Assuming that the creator of the above has defined backDoor for its normal use. But you want to access the object and see the private member variables. Even if the above class has been compiled into a static library, you can add your own specialized specialization for backDoor and thereby access members.

 namespace { // Make this inside an anonymous namespace so // that it does not clash with any real types. class Y{}; } // Now do a template specialization for the method. template<> void Z::backDoor<Y>(Y const& p) { // I now have access to the private members of Z } int main() { Z z; // Your object Z // Use the Y object to carry the payload into the method. z.backDoor(Y()); } 
+8
Jan 08 '09 at 19:13
source share

cool question btw ... here is my part:

 using namespace std; class Test { private: int accessInt; string accessString; public: Test(int accessInt,string accessString) { Test::accessInt=accessInt; Test::accessString=accessString; } }; int main(int argnum,char **args) { int x; string xyz; Test obj(1,"Shit... This works!"); x=((int *)(&obj))[0]; xyz=((string *)(&obj))[1]; cout<<x<<endl<<xyz<<endl; return 0; } 

Hope this helps.

+4
Mar 29 '11 at 9:03
source share

This answer is based on the exact concept demonstrated by @Johannes answer / blog , as it seems to be the only "legal" way. I have turned this sample code into a handy utility. It is easily compatible with C ++ 03 (by implementing std::remove_reference and replacing nullptr ).

Library

 #define CONCATE_(X, Y) X##Y #define CONCATE(X, Y) CONCATE_(X, Y) #define ALLOW_ACCESS(CLASS, TYPE, MEMBER) \ template<typename Only, TYPE CLASS::*Member> \ struct CONCATE(MEMBER, __LINE__) { friend TYPE (CLASS::*Access(Only*)) { return Member; } }; \ template<typename> struct Only_##MEMBER; \ template<> struct Only_##MEMBER<CLASS> { friend TYPE (CLASS::*Access(Only_##MEMBER<CLASS>*)); }; \ template struct CONCATE(MEMBER, __LINE__)<Only_##MEMBER<CLASS>, &CLASS::MEMBER> #define ACCESS(OBJECT, MEMBER) \ (OBJECT).*Access((Only_##MEMBER<std::remove_reference<decltype(OBJECT)>::type>*)nullptr) 

API

 ALLOW_ACCESS(<class>, <type>, <member>); 

Using

 ACCESS(<object>, <member>) = <value>; // 1 auto& ref = ACCESS(<object>, <member>); // 2 

Example

 struct X { int get_member () const { return member; }; private: int member = 0; }; ALLOW_ACCESS(X, int, member); int main() { X x; ACCESS(x, member) = 42; std::cout << "proof: " << x.get_member() << std::endl; } 
+4
Jan 01 '16 at 15:25
source share

If you know how your C ++ compiler manages names, yes.

If, I suppose, this is a virtual function. But then if you know how your C ++ compiler creates VTABLE ...

Edit: Looking at the other answers, I understand that I misunderstood the question and thought it was about member functions, not member data. However, the point is still worth it: if you know how your compiler outputs data, you can access that data.

+3
Jan 08 '09 at 12:50
source share

As an alternative to the backdoor method template, you can use the backdoor class of the template. The difference is that you do not need to put this backdoor class in the public domain of the class you are going to test. I use the fact that many compilers allow nested classes to access the closed area of ​​the enclosing class (which is not the 1998 standard, but is considered to be the "right" behavior). And of course, in C ++ 11, this has become legal behavior.

See this example:

 #include <vector> #include <cassert> #include <iostream> using std::cout; using std::endl; ///////// SystemUnderTest.hpp class SystemUnderTest { //...put this 'Tested' declaration into private area of a class that you are going to test template<typename T> class Tested; public: SystemUnderTest(int a): a_(a) {} private: friend std::ostream& operator<<(std::ostream& os, const SystemUnderTest& sut) { return os << sut.a_; } int a_; }; /////////TestFramework.hpp class BaseTest { public: virtual void run() = 0; const char* name() const { return name_; } protected: BaseTest(const char* name): name_(name) {} virtual ~BaseTest() {} private: BaseTest(const BaseTest&); BaseTest& operator=(const BaseTest&); const char* name_; }; class TestSuite { typedef std::vector<BaseTest*> Tests; typedef Tests::iterator TIter; public: static TestSuite& instance() { static TestSuite TestSuite; return TestSuite; } void run() { for(TIter iter = tests_.begin(); tests_.end() != iter; ++iter) { BaseTest* test = *iter; cout << "Run test: " << test->name() << endl; test->run(); } } void addTest(BaseTest* test) { assert(test); cout << "Add test: " << test->name() << endl; tests_.push_back(test); } private: std::vector<BaseTest*> tests_; }; #define TEST_CASE(SYSTEM_UNDER_TEST, TEST_NAME) \ class TEST_NAME {}; \ template<> \ class SYSTEM_UNDER_TEST::Tested<TEST_NAME>: public BaseTest \ { \ Tested(): BaseTest(#SYSTEM_UNDER_TEST "::" #TEST_NAME) \ { \ TestSuite::instance().addTest(this); \ } \ void run(); \ static Tested instance_; \ }; \ SYSTEM_UNDER_TEST::Tested<TEST_NAME> SYSTEM_UNDER_TEST::Tested<TEST_NAME>::instance_; \ void SYSTEM_UNDER_TEST::Tested<TEST_NAME>::run() //...TestSuiteForSystemUnderTest.hpp TEST_CASE(SystemUnderTest, AccessPrivateValueTest) { SystemUnderTest sut(23); cout << "Changed private data member from " << sut << " to "; sut.a_ = 12; cout << sut << endl; } //...TestRunner.cpp int main() { TestSuite::instance().run(); } 
+1
Jul 08 '13 at 11:57
source share

The following code accesses and modifies the private member of a class with a pointer to that class.

 #include <iostream> using namespace std; class A { int private_var; public: A(){private_var = 0;}//initialized to zero. void print(){cout<<private_var<<endl;} }; int main() { A ob; int *ptr = (int*)&ob; // the pointer to the class is typecast to a integer pointer. (*ptr)++; //private variable now changed to 1. ob.print(); return 0; } /*prints 1. subsequent members can also be accessed by incrementing the pointer (and type casting if necessary).*/ 
+1
Aug 10 '14 at
source share

Next to #define private public, you can also #define private protected , and then define some class foo as a descendant of the desired class in order to have access to it (now protected) methods via type casting.

0
Jan 08 '09 at 13:01
source share

just create your own accessor function to extend the class.

0
Jan 08 '09 at 13:30
source share

For all people offering " #define private public ":

This thing is illegal . The standard prohibits the definition / deletion of macros that are lexically equivalent to reserved language keywords. Although your compiler probably won't complain (I haven't seen the compiler that does), this is not what "Good Thing" needs to do.

0
Jan 08 '09 at 16:16
source share

This is actually pretty simple:

 class jail { int inmate; public: int& escape() { return inmate; } }; 
0
Jan 08 '09 at 16:22
source share

since you have an object of the required class, I assume that you have a class declaration. Now, what you can do is declare another class with the same members, but keep all access specifications as public.

For example, the previous class:

 class Iamcompprivate { private: Type1 privateelement1; Typ2 privateelement2; ... public: somefunctions } 

you can declare a class as

 class NowIampublic { **public:** Type1 privateelement1; Type2 privateelement2; ... somefunctions }; 

Now all you have to do is point the Iamcompprivate class pointer to the NowIampublic class NowIampublic and use them as a U wish.

Example:

 NowIampublic * changetopublic(Iamcompprivate *A) { NowIampublic * B = (NowIampublic *)A; return B; } 
0
Jun 30 '10 at 9:56
source share

"Using private variables is not a reliable 100% way to force encapsulation, even in C ++." Indeed? You can parse the library you need, find all the necessary offsets and use them. This will give you the opportunity to change any private member that you like ... BUT! You cannot access private members without any dirty hacking. Let's say that writing const will not force your constant to be really constant, because you can press const or just use its address to make it invalid. If you use MSVC ++ and you specify "-merge: .rdata = .data" on the linker, the trick will work without any memory access errors. We can even say that writing applications in C ++ is not a reliable way to write programs, because the resulting low-level code can be fixed somewhere outside when your application is running. Then what is a reliable documented way to provide encapsulation? Can we hide data somewhere in RAM and prevent access to it, except for our code? The only idea I have is to encrypt private members and back them up, because something could ruin these members. Sorry if my answer is too rude, I did not want to offend anyone, but I really do not think this statement is wise.

0
Dec 22 '10 at 21:55
source share

Referring to *, you include a backdoor to all personal data inside the object.

 class DumbClass { private: int my_private_int; public: DumbClass& backdoor() { return *this; } } 
0
Jul 03 '13 at 19:32
source share

Quite often, a class provides mutator methods for private data (getters and seters).

If the class provides a getter that returns a const reference (but not a setter), you can simply const_cast return the getter value and use this as an l-value:

 class A { private: double _money; public: A(money) : _money(money) {} const double &getMoney() const { return _money; } }; A a(1000.0); const_cast<double &>(a.getMoney()) = 2000.0; 
0
Jul 16 '13 at 10:14
source share

I used another useful approach (and solution) to access a private / protected C ++ element.
The only condition is that you can inherit the class you want to access.
Then all credits are transferred to reinterpret_cast <> () .

A possible problem is that it will not work if you introduce a virtual function that changes the virtual table, and therefore the size of the object / alignment.

 class QObject { Q_OBJECT Q_DECLARE_PRIVATE(QObject) void dumpObjectInfo(); void dumpObjectTree(); ... protected: QScopedPointer<QObjectData> d_ptr; ... } class QObjectWrapper : public QObject { public: void dumpObjectInfo2(); void dumpObjectTree2(); }; 

Then you just need to use the class as follows:

 QObject* origin; QObjectWrapper * testAccesor = reinterpret_cast<QObjectWrapper *>(origin); testAccesor->dumpObjectInfo2(); testAccesor->dumpObjectTree2(); 

My initial problem was this: I need a solution that does not imply recompiling the QT libraries.
There are 2 methods in QObject, dumpObjectInfo () and dumpObjectTree (): just work if the QT libs are compiled in debug mode, and of course they need access to the protected member d_ptr (among other internal structures).
What I did was use the proposed solution to override (with copy and paste) these methods in dumpObjectInfo2 () and dumpObjectTree2 () in my own class (QObjectWrapper), removing these protective wrappers for preliminary debugging.

0
Apr 08 '14 at 15:31
source share

Learning is the only goal .... try this .... it may be useful, I think ..... this program can access sensitive data just by knowing the values ​​...

 //GEEK MODE....;) #include<iostream.h> #include<conio.h> class A { private :int iData,x; public: void get() //enter the values {cout<<"Enter iData : "; cin>>iData;cout<<"Enter x : ";cin>>x;} void put() //displaying values {cout<<endl<<"sum = "<<iData+x;} }; void hack(); //hacking function void main() {A obj;clrscr(); obj.get();obj.put();hack();obj.put();getch(); } void hack() //hack begins {int hck,*ptr=&hck; cout<<endl<<"Enter value of private data (iData or x) : "; cin>>hck; //enter the value assigned for iData or x for(int i=0;i<5;i++) {ptr++; if(*ptr==hck) {cout<<"Private data hacked...!!!\nChange the value : "; cin>>*ptr;cout<<hck<<" Is chaged to : "<<*ptr; return;} }cout<<"Sorry value not found....."; } 
-one
Sep 18 '16 at 18:11
source share
 class Test{ int a; alignas(16) int b; int c; }; Test t; 

Method A: Intrusive mood. since we can access the source code and reformulate it, we can use many other methods, like a class of friends to access a private member, all of them are legitimate backdoors.

method B: rude mood.

 int* ptr_of_member_c = reinterpret_cast<int*>(reinterpret_cast<char*>(&t) + 20); 

we use the magic number (20), and it is not always correct. When the layout of the Test class has changed, magic numbers are a big source of errors.

Method C: Super Hacker Mood. is there any non-intrusive and non-rude mood? since information about the object of the Test class is hidden from the compiler, we cannot get information about the offset from the mouth. ex.

 offsetof(Test,c); //complie error. they said can not access private member. 

we also cannot get a member pointer from the Test class. ex.

 &Test::c ; //complie error. they said can not access private member. 

@Johannes Schaub - litb has a blog, he found a way to rob a private member of the pointer. but I thought it should be a bug fix or language trap. I can execute it on gcc4.8 but not on vc8 complier.

, therefore, the conclusion may be as follows: the owner builds all the backdoor. a thief always has a rude and bad way to penetrate. A casual hacker has an elegant and automatic way to infiltrate.

-2
Sep 11 '14 at 2:25
source share



All Articles