본문 바로가기

Pwnable.kr

Pwnable.kr [uaf]

#include <fcntl.h>
#include <iostream> 
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;

class Human{
private:
	virtual void give_shell(){
		system("/bin/sh");
	}
protected:
	int age;
	string name;
public:
	virtual void introduce(){
		cout << "My name is " << name << endl;
		cout << "I am " << age << " years old" << endl;
	}
};

class Man: public Human{
public:
	Man(string name, int age){
		this->name = name;
		this->age = age;
        }
        virtual void introduce(){
		Human::introduce();
                cout << "I am a nice guy!" << endl;
        }
};

class Woman: public Human{
public:
        Woman(string name, int age){
                this->name = name;
                this->age = age;
        }
        virtual void introduce(){
                Human::introduce();
                cout << "I am a cute girl!" << endl;
        }
};

int main(int argc, char* argv[]){
	Human* m = new Man("Jack", 25);
	Human* w = new Woman("Jill", 21);

	size_t len;
	char* data;
	unsigned int op;
	while(1){
		cout << "1. use\n2. after\n3. free\n";
		cin >> op;

		switch(op){
			case 1:
				m->introduce();
				w->introduce();
				break;
			case 2:
				len = atoi(argv[1]);
				data = new char[len];
				read(open(argv[2], O_RDONLY), data, len);
				cout << "your data is allocated" << endl;
				break;
			case 3:
				delete m;
				delete w;
				break;
			default:
				break;
		}
	}

	return 0;	
}

uaf에 대한 공부는 했었지만 실제로 문제로 접해본 것은 처음이었다.

 

개념은 간단히 heap 영역에 메모리를 할당과 해제할 때,

메모리 할당 크기에 따라서 bin이라는 그룹 개념으로 관리한다. 

그리고 메모리 해제 후 해당 메모리와 같은 그룹의 메모리를 재할당하면, 이전에 해제한 주소에 할당을 하게 된다.

이 때 파일 시스템에서 flags값만 지우고 데이터가 남아있는 것처럼

heap에서도 남아있는 데이터가 leak과 reuse가 가능해지는 취약점이다. 

 

이 문제에서는 가장 작은 그룹인 fastbin을 사용하는 것으로 보인다. 

애매하게 적은 이유는 fastbin의 경우 8~64byte의 메모리를 할당할 경우

80byte씩 할당을 해준다고 하는데, man과 woman 다 80byte를 할당 받았지만

data에 할당을 8~24의 크기로 할 때만 해당 영역을 할당 받았다. 

 

bin에 대한 자세한 정보는 나중에 필요하면 더 보는 거로 ㅎ

 

위 함수가 new Man("Jack", 25)에 해당하는 코드로 보인다.

할당되는 heap 주소가 arg[0]이다. 

 

Woman의 경우 main+173에 new Woman("Jill", 21)이 있다.

 

할당을 한경우 위와 같이 데이터가 들어간다.

 

입력값 1을 사용했을 경우 ->introduce();를 실행하는 부분인데,

할당된 주소에서 +8값을 rdx에 넣고, rdx를 콜한다. 

 

해당 주소와 rdx값을 확인해보면 introduce()함수를 호출하는 것을 재확인 할 수 있다. 

 

이후 free된 상태에서의 메모리 정보이다.

Linked list의 형태로 사용가능한 영역들을 가리키고 끝에는 0을 가리킨다.

 

메모리 할당을 통해 해당 주소를 한번 덮고, 다시 call rdx 부분으로 돌아가면 

원래 m->introduce();의 코드가 [[m]+8]을 호출하는 거에서

내가 재할당해서 덮은 값 +8(0x401568+8 == 0x401570 --> 0x40117a <give_shell>)을 호출하게 된다. 

 

call rdx 시점에서의 rdx값이다.

 

이렇게 하면 give_shell 함수 호출로 쉘을 얻게되고 플래그를 얻을 수 있다.

 

주소값은 그냥 tmp폴더에 파일에다가 주소값 넣어주고, argv[2]로 전해주면 된다. 

'Pwnable.kr' 카테고리의 다른 글

Pwnable.kr [asm]  (0) 2019.05.08
Pwnable.kr [memcpy]  (0) 2019.05.08
Pwnable.kr [cmd2]  (0) 2019.05.03
Pwnable.kr [cmd1]  (0) 2019.05.02
Pwnable.kr [lotto]  (0) 2019.05.02