what is c++ shared_ptr
c++ 문제를 풀다보니
C
Smart *smart = new Smart();
std::shared_ptr<Smart> src_ptr(smart);
std::shared_ptr<Smart> new_ptr(smart);다음과 같은 코드가 나왔다. 처음 보는 생소한 코드여서 알아보도록 하자
shared_ptr 객체는 한가지 포인터에 대해 다같이 사용할 수 있게 해주는 객체이다. 몇개가 해당 포인터에 이어져 있는지도 확인할 수 있으며, 마지막으로 이어진 곳에서 포인터를 놓을때 해당 shared_ptr의 메인 객체도 free가 되어 메모리를 관리하기 쉽게 되어있다.
C
pwndbg> stack
00:0000│ rsp 0x7fffffffe070 ◂— 0
01:0008│-058 0x7fffffffe078 —▸ 0x6172b0 —▸ 0x4015b4 (apple()) ◂— pushq %rbp
02:0010│-050 0x7fffffffe080 —▸ 0x6172b0 —▸ 0x4015b4 (apple()) ◂— pushq %rbp
03:0018│-048 0x7fffffffe088 —▸ 0x6172d0 —▸ 0x402300 (vtable for std::_Sp_counted_ptr<Smart*, (__gnu_cxx::_Lock_policy)2>+16) —▸ 0x401fe0 (std::_Sp_counted_ptr<Smart*, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr()) ◂— pushq %rbp
04:0020│-040 0x7fffffffe090 —▸ 0x6172b0 —▸ 0x4015b4 (apple()) ◂— pushq %rbp
05:0028│ rcx rdi 0x7fffffffe098 —▸ 0x6172f0 —▸ 0x402300 (vtable for std::_Sp_counted_ptr<Smart*, (__gnu_cxx::_Lock_policy)2>+16) —▸ 0x401fe0 (std::_Sp_counted_ptr<Smart*, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr()) ◂— pushq %rbp
06:0030│-030 0x7fffffffe0a0 ◂— 0
07:0038│-028 0x7fffffffe0a8 ◂— 0
pwndbg> x/3gx 0x6172d0
0x6172d0: 0x0000000000402300 0x0000000100000001
0x6172e0: 0x00000000006172b0
pwndbg> 생성 했을때 스택에 저장되는 것을 살펴보면
C
02:0010│-050 0x7fffffffe080 —▸ 0x6172b0 —▸ 0x4015b4 (apple()) ◂— pushq %rbp
03:0018│-048 0x7fffffffe088 —▸ 0x6172d0 —▸ 0x402300 (vtable for std::_Sp_counted_ptr<Smart*, (__gnu_cxx::_Lock_policy)2>+16) —▸ 0x401fe0 (std::_Sp_counted_ptr<Smart*, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr()) ◂— pushq %rbp16바이트를 차지하고
첫번째 8바이트에는 sharded 하고 있는 메인 객체의 주소를 나타낸다 ( 0x6172b0 )
두번째 8바이트에는 control block 객체의 주소를 나타낸다. ( 0x6172d0 )
해당control block을 봐보면
C
pwndbg> x/5gx 0x6172d0
0x6172d0: 0x0000000000402300 0x0000000100000001
0x6172e0: 0x00000000006172b0 0x0000000000402300 → vtable 주소 ( shared_ptr가 가지고 있는 destroy(), dispose() 같은 내부 가상 함수 주소들 )
0x0000000100000001 → 각각 4바이트로 각각 weak_count , use_count (shared count) 0x00000000006172b0 → 메인 객체의 주소 와 같은 정보들을 담고 있다.
vulnerability
참고로 위에서 보았던,
C
Smart *smart = new Smart();
std::shared_ptr<Smart> src_ptr(smart);
std::shared_ptr<Smart> new_ptr(smart);이런 사용법은 완전히 위험하고 의도와 맞지 않은 코드이다.
이러면 smart에 대해서 각각 공유하고 있다고 생각하기에 2개가 서로 공유를 하던 의도랑 완전히 달라질 수 있다. ( uaf가 가능하게 됨 )
따라서, 아래와 같이 사용해야 한다.
C
Smart* smart = new Smart();
std::shared_ptr<Smart> src_ptr(smart);
std::shared_ptr<Smart> new_ptr = src_ptr; C
std::shared_ptr<Smart> smart = std::make_shared<Smart>();
std::shared_ptr<Smart> src_ptr(smart);
std::shared_ptr<Smart> new_ptr(smart);