#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;
}
User After Free
동적할당(Dynamic memory allocated) 된 heap을 free하고 다시 재사용(Dynamic memory reuse) 할 때에 취약점이 발생할 수 있다.
Deferred Coalescing (병합 지연)
malloc -> caching free된 heap이 다음에 realloc될 때에 같은 사이즈로 요청받을 수 있습니다. 이 때 heap을 병합하거나 분할하는 시간을 절약하고자 free된 heap을 남겨뒀다가 reuse할 때 그대로 쓰게 해주는 방법입니다.
--->>>gdb--->>>>
분기문이 있고 1을 입력했을 경우를 introduce()가 실행되는 과정에서 introduce 주소의 위치를 알아야 하기 때문에 main+265에 bp를 걸고 프로그램을 실행시켜 보자. 0x400fcd로 jmp하고 차례대로 코드가 실행 될 것이다.
코드를 보면 Human 클래스의 virtual function인 give_shell()을 호출하는 부분이 보이지 않는다. 하지만 같은 클래스의 객체끼리 가상함수를 모아 놓고 사용하는 개념인 vtable을 이용해 1 use에서 introcude() 호출 대신 give_shell()를 호출하도록 만든 것이다.
main+286에서 함수를 call하는데 introduce() 함수를 실행하는 부분이다.
main+272 부분에서 rax에 give_shell 함수의 주소에 +8을 해준다 이 값이 rdx로 들어가는 것을 알 수 있다.
다음으로 힙에 할당된 Man객체를 내부를 보기로 한다.
heap에 이름이 있는데 객체는 name 문자열의 포인터를 가지고 있다.
Man의 객체아래 바로 Woman의 객체도 함께 생성되어 있는 것을 볼 수 있다.
tmp/oieh/file에 "AAAA"를 써주고 프로그램을 실행 시켰다.
3 -> 2 ->1 한번만 free를 해주고 데이터를 썻더니 w->introduce()는 덮혔지만
m->introduce() 주소가 0x00000000으로 되어 프로그램 segment fault가 떠 종료된다.
그리하여 3 -> 2 -> 3 -> 2 -> 1 과 같이 두번 free와 data을 썻다.
아래와 같이 의도한 메모리 위치에 값을 넣어 줄 수 있었다.
"AAAA"문자열 대신에 0x401570(introduce함수) -0x8 = 0x401568(give_shell함수)값을 넣어주면 쉘이 실행된다.
'System Hacking > pwable.kr' 카테고리의 다른 글
18.pwnable asm (0) | 2018.02.28 |
---|---|
17.pwnable memcpy (0) | 2018.02.28 |
15.pwnable cmd2 (0) | 2018.02.23 |
14.pwnable cmd1 (0) | 2018.02.23 |
13.pwnable lotto (0) | 2018.02.23 |