Level9
level9로 로그인 후 cat hint를 입력해 힌트 파일을 확인한다.
bof 파일의 코드에 대해 분석해 보면 다음과 같다.
크기가 10인 char형 배열 buf2와 buf를 정의한다.
fgets 함수를 통해 크기 40만큼의 값을 입력받고, buf에 삽입한다.
이때, buf2의 앞 두 자리가 go라면 level10의 권한(uid: 3010)으로 bash를 실행한다.
buf2에 값을 직접 입력할 수 없는 점, buf2의 값에 따라 level10 권한으로 bash를 실행할 수 있는 점(, 그리고 파일 이름이 bof인 점) 등으로 미루어 보았을 때, 이 문제는 버퍼 오버플로우를 이용해야 한다는 것을 알 수 있다.
*버퍼 오버플로우란?
: 버퍼 오버플로(영어: buffer overflow) 또는 버퍼 오버런(buffer overrun)은 메모리를 다루는 데에 오류가 발생하여 잘못된 동작을 하는 프로그램 취약점이다. 컴퓨터 보안과 프로그래밍에서는 프로세스가 데이터를 버퍼에 저장할 때 프로그래머가 지정한 곳 바깥에 저장하는 것을 의미한다. 벗어난 데이터는 인접 메모리를 덮어 쓰게 되며 이때 다른 데이터가 포함되어 있을 수도 있는데, 손상을 받을 수 있는 데이터는 프로그램 변수와 프로그램 흐름 제어 데이터도 포함된다. 이로 인해 잘못된 프로그램 거동이 나타날 수 있으며, 메모리 접근 오류, 잘못된 결과, 프로그램 종료, 또는 시스템 보안 누설이 발생할 수 있다. (출처: 위키백과 '버퍼 오버플로')
코드 전체를 복사해 /tmp 폴더에 c 파일을 만들고, gcc -o bof_code bof_code.c 명령어를 입력해 컴파일을 해 준다.
파일 목록을 확인해 보면 정상적으로 컴파일이 된 것을 확인할 수 있다.
이제 gdb를 이용해 buf와 buf2의 메모리 주소를 파악해 버퍼 오버플로우를 유도하면 buf2에 접근할 수 있다.
*gdb?
: 유닉스 기반의 시스템에서 동작하는 디버거 중 하나
fgets(buf, 40, stdin); 코드엔 총 3개의 인자가 전달된다.
이 인자들이 스택에 들어갈 땐 stdin(<main+35>), 40(<main+41>), buf(<main_43>) 순서로 들어가게 된다.
따라서 buf의 메모리 주소는 [ebf-40]인 것을 알 수 있다.
같은 방법으로 strncmp를 기준으로 코드를 분석했을 때, buf2의 메모리 주소는 [ebf-24]인 것을 알 수 있다.
buf와 buf2 사이에 총 16byte의 차이가 존재하기 때문에, 16자리를 입력한 후 17자리부터 입력하는 데이터는 buf2에 저장된다.
진짜 되는지 확인해 보자.
bof를 실행한 뒤 kkkkkkkkkkkkkkkkgo를 입력하면 level10의 권한으로 bash가 실행된다.
my-pass를 입력해 level10의 password를 얻을 수 있다.
Level10
level10으로 로그인 후 cat hint를 입력해 힌트 파일을 확인한다.
공유 메모리를 이용해 통신 중이며, key_t의 값이 7530이라는 것을 확인했다.
*공유 메모리?
: 컴퓨터 환경에서 여러 프로그램(프로세스)이 동시에 접근할 수 있는 메모리 (출처: 위키백과 '공유 메모리')
ipcs -m 명령어를 입력해 확인해 보면 다음과 같이 공유 메모리 하나를 발견할 수 있다.
0x0001d6a = 0001110101101010 = 7530
공유 메모리 확인을 위해 코드를 작성한 후 컴파일해 프로그램을 만든다. (오타 수정: 1024 -> 1028)
코드 설명은 아래와 같다.
id = shmget(7530, 1028, IPC_CREAT); // 순서대로 key, 메모리 크기, 옵션. 정상적일 경우 메모리의 id 반환
memory = shmat(id, NULL, SHM_RDONLY); // 순서대로 id, 할당된 주소, 모드. 읽기 전용이라 SHM_RDONLY
// shmat의 반환값으로 memory를 통해 메시지 확인 가능
출력 성공!
패스워드를 확인할 수 있다.
Level11
level11로 로그인 후 cat hint를 입력해 힌트 파일을 확인한다. ./attackme의 소스코드 같다.
argv[1]의 값을 출력하는지 직접 확인해 보자.
우리가 입력한 kkk hi가 출력되는 것을 알 수 있다.
이 문제에선 출력을 해 주는 printf의 취약점을 이용한 해킹에 대해 실습한다.
문자열 대신 %x%x...라는 포맷스트링을 입력하면 다음과 같이 메모리 주소 같은 16진수 값을 출력한다.
이를 이용해 포맷 스트링 공격을 수행할 수 있다.
* 포맷 스트링 공격?
: 포맷스트링 공격(Format String Attack)이란 포맷스트링과 이것을 사용하는 printf() 함수의 취약점을 이용하여 RET의 위치에 셸 코드의 주소를 읽어 셸을 획득하는 해킹 공격이다. 기존에 널리 사용되던 버퍼 오버플로우(Buffer Overflow) 공격 기법에 비교되는 강력한 해킹 기법이다. (출처: 해시넷 위키 '포맷스트링 공격')
Level11은 팀원들이 아직 포맷 스트링 공격이 익숙하지 않은 관계로, 개념을 숙지한 후 다시 해결할 예정.
'3. Pwnable (포너블) > 2) 개념 정리' 카테고리의 다른 글
[2021.11.07] OverTheWire 0-10, 달고나문서 -p.12 (0) | 2021.11.06 |
---|---|
[2021.09.25] 해커스쿨 F.T.Z Level11~15 풀이 (0) | 2021.09.26 |
[2021. 09. 11] 해커스쿨 F.T.Z를 통한 기초 명령어 실전 활용 (0) | 2021.09.12 |
[2021. 09. 04] 해커스쿨 F.T.Z를 통한 리눅스 기초 명령어 습득 (0) | 2021.09.04 |
[2021.05.22] 8주차 : Bandit Level 15,16,17->18 | 달고나 문서 p.34 ~ ~ p.44 (0) | 2021.05.22 |