ipwn

[pwnable.kr] uaf 본문

Write up/Pwnable.kr

[pwnable.kr] uaf

ipwn 2018. 2. 19. 16:19

uaf를 공부한 김에 pwnable.kr uaf문제를 풀어봤다.


생각한 시나리오가 맞지 않아서 엄청 오래걸렸다.... 그리고 풀긴 풀었지만 이해가 가지 않는 부분도 많다...



uaf가 어떤 취약점인지 묻는 문제이다.


사실 C++을 잘 몰라서 왜 이렇게 동작하는지는 모르겠지만, 일단 레지스터 이용해서 호출하고 그러는 거 보고 풀었다.




코드는 이렇다.


사실 코드는 제대로 이해하지 못했지만, 클래스 하나하나를 구조체라고 이해하고 풀어봤다.


설명을 잘 할 자신은없지만 일단 human형 m, w라는 변수를 선언하고, 거기에 man, woman형의 크기만큼 동적할당을 

해주고 값을 집어넣는 것 같다.(모르겠다.. C++을 공부해야할 이유가 계속 생긴다.)


그리고 case1번에서는 각 m, w의 introduce함수를 호출한다.

2번에서는 data 변수에 argv[1]의 크기만큼, argv[2]의 이름을 갖고있는 파일 내의 값으로 동적할당 해준다.

그리고 3번에서는 할당을 해제해준다.


일단 확실한건 uaf취약점을 이용해 introduce함수포인터를 조작해, give_shell함수를 호출하는 문제인 것 같다.


일단 gdb로 디버깅 해보겠다.


(set print asm-demangle on을 미리 쳐주면 C++ 바이너리를 디버깅 할 때 글자 깨짐이 사라진다!! 신기하다..)



이 부분이 switch case문이라는 것을 파악할 수 있다.


한 번 case 1번 즉 introduce를 호출하는 구간을 보겠다.



보면 rbp-0x38에 있는 값을 rax에 넣어주고 rax안에 있는 값을 rax에 넣고 rax+8을한 값을 rdx에 넣어준 뒤 rdx를 호출한다.

즉 레지스터를 주욱 따라가면 introduce함수가 나온다. 한 번 bp를 걸고 따라가보겠다.


rax가 +8되기 전에 bp를 걸겠다.



한 번 rax의 값을 보겠다.



rax가 +8되기 전의 값은 give_shell을 가리킨다.



rax + 8의 값은 예상대로 introduce의 주소를 갖고있다.

아마 rax +8이 되기전 값 - 8로 변조를 해주면 introduce를 호출하는 것이 아닌 give_shell을 호출할 것이다.


한 번 free를 시켜보고 다시 use 해보겠다. 아직 인자를 넘겨주지 않았기 때문에 after은 조금 이따 시도하겠다.



이렇게 rax의 값은 0을 갖게 된다.

그리고 continue를 해주면 segmentation fault를 뿜으며 프로그램이 종료된다.



이렇게 값을 넘겨주고 한 번 실행시킬 때 인자로 넘겨준 뒤 디버깅 해보겠다.


각 상황별로 힙 구간을 보기 편하게 bp를 걸고 메모리를 보겠다.



이제 한 번 use free after을 할 때의 메모리를 확인해보겠다.

use는 건너뛰고 한 번 free를 한 뒤의 메모리를 살펴보겠다.



원래 있었던 함수포인터가 사라지고 이상한 값들로 채워져있다.

한 번 after로 새로 할당해보겠다.



재 할당을 해주자, 함수포인터의 위치에 0x41414141의 값이 채워진다.

한 번 다시 after 해보겠다.



이렇게 함수포인터의 값들이 전부 0x41414141로 바뀐 것을 알 수 있다.


즉 AAAA의 값이 함수포인터의 위치에 넘겨졌다는 것인데, 이 말은 즉슨 give_shell을 가르키는 주소 -8의 값을 넘겨주고 

use를 한다면, give_shell이 실행된다는 말이다.



0x40117a의 값은 give_shell함수의 주소를 의미하는데, 그 곳을 가르키는 값은 0x401570이라는 것을 위에서 알 수 있다.

그런데 rax+8을 한 값을 rdx에 넣고 rdx를 호출하므로 이 0x401570-8을 한 값을 파일에 넣어주고 

그 값을 인자로 넘겨주면 될 것이다.

(0x401550도 give_shell을 가르키고 있다. 즉 0x401550-8을 한 값을 인자로 넘겨주어도 될 것이다.)


한 번 예상대로 될지 실행해보겠다.



0x401570-8의 값은 0x401568인 것을 알 수 있다.

이제 file안의 값을 0x401568로 넘겨주고 프로그램을 한 번 실행해보겠다.



성공적으로 결과가 나왔다.


너무 어거지로 푼 것 같아서 기분이 묘하긴한데, 일단은 푼 것이니 라업을 올렸습니다.

틀린 부분이나, 부족한 부분이 있으면 피드백 부탁드리겠습니다..ㅠㅠ

아직 한참 모자라다는 걸 여러모로 많이 느낍니다..

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

[pwnable.kr] input  (0) 2018.03.13
[pwnable.kr] coin1  (0) 2018.03.12
[pwnable.kr] shellshock  (0) 2018.01.06
[pwnable.kr] mistake  (0) 2018.01.06
[pwnable.kr] cmd2  (0) 2018.01.04
Comments