-
[L.O.B] Level 4 - goblinWargame/L.O.B 2022. 10. 12. 07:21반응형
Level4 - goblin을 풀어보자.
취약한 함수와 NOP Sled에 대해서 새롭게 알게 된 부분이 생겼다!!
소스 코드를 살펴보자.
다음 Level의 이름은 orc인 듯하고, 이번 문제는 egghunter라는 내용이 추가되어 있다.
가장 먼저 눈에 띄는 것은 extern char **environ; 이라는 구문이다.
environ은 man environ으로 자세한 정보를 알 수 있는데, 간단하게 환경변수의 리스트라고 생각하면 되겠다.
40 바이트 크기의 char 형 배열 buffer를 선언하고, int 형의 i를 선언한다.
다음으로 파일을 실행하면서 들어올 인자의 수가 2개 미만이라면 argv error를 출력하며 종료된다.
그 다음, egghunter의 설명이 있다.
memset 함수로 environ 리스트의 값들을 0으로 만들어버린다.
이것으로 인해 앞의 Level 들에서 했던 환경변수를 이용한 풀이는 하지 못하게 되었다.
그리고 if 문이 하나 더 나오는데, 입력하는 인자의 48번째 값이 '\xbf'가 아니라면 문구를 출력하며 종료된다.
마지막으로 strcpy 함수로 인자의 값을 buffer에 복사하고, buffer를 출력한다.
앞에 몇 가지 조건들이 있긴 하지만, 결론적으로는 strcpy 함수를 사용하니 overflow 공격을 할 수 있겠다.

<orc.c 소스 코드의 내용> gdb를 이용해 orc를 분석해보자.
<main+3>에서 esp에 44 바이트를 빼는 것으로 보아 int i의 4 바이트와 buffer의 40 바이트 공간이다.
dummy는 따로 없고, buffer와 ret 까지의 거리는 40 바이트 + 4 바이트(SFP) = 44 바이트라고 알 수 있다.
strcpy 함수의 인자로 들어갈 buffer의 위치를 알려주는 <main+185>를 보면 다시 확인을 할 수 있다.


<gdb를 이용한 orc 분석> 이번 Level은 환경변수를 이용해 공격을 할 수 없으므로, 쉘 코드를 직접 삽입하도록 하자.
gate Level의 마지막에 직접 삽입을 하는 방법을 추가해 놓았다. (설명은 없는데, 이 글에서 하도록 하자.)
[NOP Sled]
더보기쉘 코드를 직접 삽입하기 위해 NOP Sled라는 기법을 사용하도록 하겠다.
NOP Sled는 NOP 썰매라는 의미라고 한다.
NOP는 어셈블리어에서 1바이트의 크기를 가진 아무런 의미가 없는 명령어이다.
아무런 의미가 없다는 것은 어떠한 명령도 실행하지 않고, 단지 크기만 가진다는 것이다.
그렇다면 이 NOP를 어떻게 공격에 이용하는 것일까??
프로그램 상에서 NOP 명령어가 나타나면 크기만 차지하고, 다음 명령으로 넘어간다.
앞의 Level 들에서는 쉘 코드를 삽입한 환경변수를 선언하고, 그 주소를 ret에 넣는 것으로 공격을 시도했다.
그런데 이번에는 환경변수를 선언할 수 없으니, 직접 쉘 코드를 넣어야 하는데 그 주소를 모른다.
이럴 때 NOP를 쉘 코드의 앞에 넣어주어 쉘 코드의 주소에 대한 오차 범위를 넓혀준다.
그래서 NOP를 타고 쉘 코드까지 가는 것을 썰매를 타고 지나가는 것처럼 표현해 NOP Sled라고 부른다.
간단한 설명이 끝났고, 문제를 이어서 풀어보자.
현재 buffer(40) + sfp(4) + ret(4)의 형태로 스택이 구성되어 있다.
해결을 위해서는 buffer에 쉘 코드를 넣고, ret에 buffer의 주소값을 넣어 실행시키면 된다.
buffer의 주소를 알아보기 위해 gdb 분석을 수행하자.
먼저 현재 사용자인 goblin의 권한으로 orc 파일을 실행하기 위해 /tmp에 orc 파일을 복사한다.
다음으로 gdb를 실행하고, strcpy가 끝나는 지점인 main+194에 break point를 잡아준다. (esp를 알기 위해)
r로 실행을 시키면서 python을 이용한 명령을 입력한다.
중요한 것은 48번째 값이 '\xbf'인 것을 잊으면 안된다. (문구를 출력하며 종료처리되어 실행되지 않음)
0xbffffa94의 4번째 값부터 입력한 a가 나오고 있다.
하나의 값 당 4 바이트이므로 0xbffffa94 + 12 = 0xbfffaa0이라고 할 수 있다.
하지만, gdb 분석에서의 주소와 실제 주소는 차이가 있을 수 있다. (프로그램명 길이에 따라 달라진다.)
그래서 취약한 함수, NOP Sled에 대해 알게 된 새로운 사실을 이용해 공격을 하도록 하자.
(orc.c 소스 코드에 buffer의 주소값을 출력하는 함수를 넣어 buffer의 정확한 주소 값을 알 수도 있지만, 여기서는 이 방법으로 풀이를 하지는 않겠다.)

<buffer의 주소> 취약한 함수는 어떤 부분 때문에 취약하다고 하는 것일까??
입력의 크기가 지정되어 있지 않아, buffer의 크기를 초과한 입력이 가능해 ret까지 도달할 수 있다는 것이다.
그런데 정확히는 buffer의 경계값을 검사하지 않는다는 점 때문에 취약한 것이다.
이 취약점은 어마어마해서, ret를 넘어갈 수도 있다!! (새롭게 알게 되었다.)
그렇다면 buffer에 NOP를 잔뜩 넣어 ret를 넘어가는 값에 NOP Sled를 이용한 쉘 코드를 실행할 수도 있다.
아래의 페이로드를 보면, buffer와 sfp의 44 바이트만큼 NOP를 채웠다.
다음으로 buffer 내의 주소들 중 하나인 0xbfffffab4를 ret에 넣어 if 문을 만족하면서 ret를 넘게 했다.
그리고 NOP를 적절한 수만큼 넣고 쉘 코드를 삽입하니 쉘이 실행되었다. (NOP 250개 X -> 500개 O)
그 후 my-pass를 입력하니 비밀번호가 나타났다.

<나타난 비밀번호> 반응형'Wargame > L.O.B' 카테고리의 다른 글
[L.O.B] Level 6 - wolfman (0) 2022.10.14 [L.O.B] Level 5 - orc (0) 2022.10.13 [L.O.B] Level 3 - cobolt (2) 2022.10.11 [L.O.B] Level 2 - gremlin (0) 2022.10.11 [L.O.B] Level 1 - gate (1) 2022.10.10