# 1. UAF란?
UAF는 Use After Free의 약자로 malloc등으로 동적할당한 데이터 영역(Heap)을 free를 이용, 해제한 뒤에 사용을 할 경우 생기는 에러이다.
< Use After Free >
그림에서 처럼 Allocated, 할당되어 있는 데이터를 Use, 사용하면 문제가 없지만, 해당 영역을 Free를 한 후에 Use를 하면 Terminal이 된다는 의미이다.
# 2. Pwnable.kr uaf
● UAF 확인
문제의 소스는 아래와 같다.
각각 Use -> 출력, After -> 할당, Free -> 할당 해제를 의미한다.
# 1의 그림에서 처럼 에러를 터트려보면 다음과 같다.
< UAF error >
소스를 보면 알겠지만 처음에 기본적으로 할당되어있는 데이터가 있다.
이 데이터를 Use 메뉴를 이용, 출력을 하면 문제없이 출력이 된다.
하지만 Free를 한 후에 다시 Use를 이용하여 출력을 하면 Segmentation Falut가 발생한다.
● Heap 할당 주소 확인
< Woman Call after rax >
Woman Function을 Call한 이후 rax의 값을 확인해보면 0x252a090이 들어있다.
이는 Human* w = new Woman("Jill", 21);의 리턴으로 돌아온 동적할당된 Heap 주소이다.
당연히 Heap 영역이기 때문에 프로그램 실행마다 매번 바뀐다.
Woman할당 이후 0x25a090가 가리키는 값을 보면 Woman+16을 가리키고 이는 giveshell의 주소이다.
뒤에서 보겠지만 어찌되었건 여기서 확인을 할 수 있는 것은 Woman Function Call 리턴으로 오는 함수의 주소가 원래는 give shell을 가리키고 있었으나 free를 하면 초기화 된다는 것이다.
● Introduce 호출까지의 확인
< m->introduce( ) >
이 부분은 switch문에서 분기하여 use를 선택하였을 경우 m->introduce( ) 호출까지의 어셈블리어이다.
mov -0x38(%rbp), %rax
-> 위에서 저장되었던 0x25a090이 rax로 저장된다.
mov (%rax), %rax
-> rax(0x25a090)가 가리키고 있는 값, Woman+16을 rax에 저장한다.
add $0x8, %rax
-> rax는 현재 Woman+16을 가리키고 있으며 +0x8을 하므로 Woman+24를 가리킨다. 이는 introduce()의 주소이다.
mov (%rax), %rdx
-> rax가 가리키고 있는 introduce()의 주소를 rdx에 저장한다.
...
*%rdx
-> introduce 함수를 호출한다.
introduce함수의 호출까지의 어셈블리어를 보면 원래 가리키고 있던 giveshell 주소에 +0x8을 한다.
따라서 giveshell을 호출하는 것이 아니라 introduce를 호출하게 된다.
● After 덮어쓰기 확인
< Free - After - Use >
0xbd8090은 위에서 rax, 0x25a090와 같다. 실행을 다시 시켜 주소가 바뀌었다.
보면 Free -> Allocated -> Use 순으로 진행을 하였다.
원래 0xbd8090에는 Woman+16(giveshell)의 주소가 있어야 정상이다.
하지만 여기서는 0x64636261이 저장되어있다. 이는 직접 입력한 abcd가 들어간 값이다.
After를 시행하면 Free를 한 역순으로 다시 할당이 된다. 즉, delete m -> delete w 순으로 하였으므로
먼저 w가 저장되어있던 Heap영역에 데이터가 할당되고 그 다음 m이 저장되어있던 Heap 영역이 할당된다.
결과적으로는 이 부분을 쉘을 띄울 수 있는 giveshell을 가리킬 수 있는 주소로 변경하면 된다.
단, 주의해야 할 점은 위에서 보았듯이 저장된 주소에 +0x8을 한다는 점이다. 따라서 giveshell을 가리키는 Woman+16의 주소에 -0x8을 한 주소를 넣어줘야 한다.
위에서 Woman의 giveshell의 주소는 0x401550이었으므로 여기서 -0x8을 한 0x401548을 넣어주면 된다.
introduce를 호출하는 방식이 m->introduce( ) >> w->introduce( )라는 것이다.
즉, After를 한번만 진행을 하게 되면 w가 저장되어있던 Heap 영역에는 giveshell주소가 저장되어 충분한 조건이 되었을 지라도, 먼저 호출이 되는 m영역은 아직 할당이 되지 않아 오류가 발생할 수 밖에 없다.
따라서 After는 두번 이상 진행을 해 주어야 한다.
● 최종 풀이
< shell 획득 >
위와 똑같이 하였다. 하지만 들어간 값이 0x401548, giveshell을 가리키는 주소 -0x8이다.
조건에 맞추어 두번을 Allocate 해 주고 Use를 해 보면 두 개의 쉘이 실행 된 것을 확인할 수 있다.
'old' 카테고리의 다른 글
Suninatas / Forensic 29 (디스크 이미지 분석) (0) | 2016.07.21 |
---|---|
Suninatas / System 27 (바이너리 속 어셈블리어) (0) | 2016.07.21 |
포포포포렌식 #3 (0) | 2016.07.12 |
System #1 (0) | 2016.07.08 |
포포포포렌식 #3 (0) | 2016.07.05 |