profile image

L o a d i n g . . .

article thumbnail image
Published 2021. 5. 8. 23:00

1. 문제

cpp 이다..... (잘 모르는뎁)

 

보면 Human 클래스와 Man, Woman 클래스가 상속 관계인 것 같다.

 

 

 

메인 함수

먼저 Human 형 m, w 객체가 초기화된다.

1번 : 각 객체의 introduce() 함수가 실행된다. 

 

2번 : char 형 객체가 생성된다.

argv[1] 으로 받은 크기만큼 메모리를 할당해서 data 변수가 가르키도록 한다.

그리고 argv[2] 로 입력받은 파일을 열어서 len byte 만큼 데이터를 읽고 읽은 데이터를 data 에 저장한다.

 

3번 : m, w 객체가 free 가 된다.

 

 

-> 본 문제는 uaf 문제로 malloc 으로 할당한 뒤 free 후 재사용하는 방식이다.

(uaf : malloc -> free -> malloc)

 

초기화된 m, w 객체를 3을 입력하여 free 해주고, 다시 2를 입력하여 같은 크기로 새로운 객체를 생성해주면 free된 m, w 자리를 새로운 객체가 할당받으며 취약점이 발생한다. m, w객체의 introduce() 함수주소가 담긴 주소를 알아내어 쉘을 실행해주는 give_shell() 함수주소로 덮어주면 쉘을 딸 수 있을 것이다.

 

 

즉, 다음과 같은 순서일 것이다.

0. free
1. m,w와 같은 크기로 char* 을 할당
2. introduce() -> give_shell() 로 overwrite
3. introduce() 함수 실행

 

 

 

2. 문제 해결 과정

1. introduce() 주소 , give_shell() 주소

 

분기문들이 위치한 곳

 

각 분기문에 bp 를 건다.

 

1번 분기문에 bp가 걸린 모습

call rdx 부분이 introduce() 함수를 실행하는 부분이다.

rdx에는 [rax+0x8] 이 담겨있다.

rax 에 8을 더하기 전의 rax 값을 먼저 보도록 하자.

 

rax에 8을 더하기 직전에 bp 를 건다.

rax는 0x401570 라는 주소를 가르키고 있고, 이 주소를 참조하면 0x40117a 값이 나온다.

0x40117a는 give_shell() 함수의 주소이다.

즉, 0x401570 은 0x40117a 를 가르키고 있음을 알 수 있다.

 

rax에 8을 더한 후에 bp 를 건다.

rax는 0x401578 라는 주소를 가르키고 있고, 이 주소를 참조하면 0x4012d2 값이 나온다.

0x4012d2는 introduce() 함수의 주소이다.

즉, 0x401578 은 0x4012d2 를 가르키고 있음을 알 수 있다.

 

->  rax에 0x401570 대신 거기서 0x8 만큼을 뺀 값이 들어간다면 0x8이 더해진 0x401570 이 되고, give_shell() 이 실행될 것이다.

 

그렇다면 우리가 입력한 값이 어디로 저장되는지 알아야한다.

값을 free하고 재할당 해준 후, 확인해보자.

 

역시나 입력값 AAAA 가 rax 에 들어가는 걸 볼 수 있다.

 

그렇다면 입력시 rax에 들어갈 값으로 0x401568 을 주면 될 것이다.

 

 

3. 익스플로잇

익스

 

플래그 획득!

 

여기서 두 가지 의문점이 있다.

 

1. 왜 할당하는 메모리 크기가 4인가?

heap은 32bit기준 8byte 단위, 64bit기준 16byte단위로 할당되게 된다.

이 문제는 64bit이므로 3바이트를 부탁하나, 15바이트를 부탁하나 결국 16byte가 할당되게 되기 때문이다.

 

 

2. 왜 2(after)을 두 번 해주는가?

다음은 free에 대한 코드이다.

case 3:
    delete m;
    delete w;
    break;

보면 m과 w를 둘다 free한다. 그럼 일단 fastbin에 m << w 순으로 쌓여있을 것이다.

그러면 이상태에서 2로 allocation을 할 경우 LIFO구조에 의하여 w에 allocation 될 것이다.

 

이 상태에서 1번을 실행시킨다면?

case 1:
    m->introduce();
    w->introduce();
    break;

지금 free된 상태인 m의 introduce를 부르니 당연히 segmentation fault가 발생한다.

그래서 allocation을 2번 한다.

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

[Pwnable.kr] 6번 random  (0) 2021.04.08
[Pwnable.kr] 5번 passcode  (0) 2021.04.08
[Pwnable.kr] 4번 flag  (0) 2021.04.08
[Pwnable.kr] 3번 bof  (0) 2021.04.01
[Pwnable.kr] 2번 collision  (0) 2021.04.01
복사했습니다!