티스토리 뷰

HackerSchool FTZ WARGAME Solution

 

Start : 15.07.03

 

LEVEL15

 

[그림 1]

 

hint를 열어보면 [그림 1]과 같이 출력이 되는데 앞에 level14와 코드가 같은 것 처럼 보이나 사실 일부분이 조금 다르다. 우선 check 변수가 int * 형태이며, if에서 check 변수 값과 비교한 것이 아니고, check 변수에 있는 값을 역참조 한 값과 비교한다.

 

[그림 2]

 

gdb로 attackme를 열어보면 [그림 2]와 같이 출력이 되는데 buf 는 level14와 같이 [ebp-56] 부터 시작되고, cmp 를 보면 level14는 eax, 0xdeadbeef 였던 반면 이번엔 [eax], 0xdeadbeef 로 eax의 값을 역참조한 값과 비교하는 것을 확인할 수 있다.

 

[그림 3]

[그림 4]

 

일단 0xdeadbeef 라는 값을 메모리 어딘가에 저장해야 하는데 글쓴이의 경우 주소값을 찾기 쉬운 환경 변수를 선택했다. [그림 3]과 같이 환경 변수에 deadbeef 를 리틀엔디언에 맞게 저장하면 된다. 그리고 역시나 간단한 코딩을 통해 환경 변수의 주소값을 알아낸다.

 

 

[그림 5]

 

level14와 마찬가지로 40byte만큼 dummy 값을 스택에 채워주고 check 영역에는 환경 변수의 주소값을 넣어 주었다.

 

[그림 6]

 

역시나 쉘 스크립트를 실행시키면서 결과를 텍스트 파일로 리다이렉션 시킨다.

 

[그림 7]

 

그리고 여느때와 마찬가지로 파이프를 이용해 공격을 시도했으나 예상과 다르게 공격에 실패했다.

 

[그림 8]

 

공격에 실패한 이유가 환경 변수 주소값이 잘못된건가 해서 간단하게 테스트할 수 있는 프로그램을 [그림 8]과 같이 작성했다. level15의 attackme 와 같으나 중간에 printf로 test 변수에 들어간 값과 역참조를 통해 출력되는 값을 출력 해 보았다.

 

[그림 9]

 

결과를 보면 test 변수에 주소값이 정상적으로 입력이 되었으나 0xefbeadde 가 출력될거라고 예상했던 것과는 달리 엉뚱한 값이 출력되었다. 처음에 이 결과를 보고 생각했던 것은 프로그램에서 환경 변수의 주소값을 참조하려고 하면 환경 변수가 아닌 다른 곳의 주소를 참조하는 것이라고 생각해 불가능한 방법이라고 생각했었으나 방법을 계속 찾다가 결국에는 환경 변수 주소를 넣어도 분명 공격이 성공 해야한다는 결론에 이르렀다. 왜냐하면 일반적인 버퍼 오버플로우 공격 때도 RET 값을 환경 변수의 주소값으로 덮어쓰기 때문이다. 그러다가 환경 변수에 쉘 코드를 저장할 때 "\x90"x100 을 입력하는 이유에 대해 다시 한번 생각하게 되었다.

 

환경 변수의 주소값은 디렉토리의 경로나 프로그램의 변수 개수 등에 의해 주소값이 밀려서 달라지게 되는데 본인이 주소값을 출력한 프로그램은 변수 할당을 따로 하지 않았고, 심지어 디렉토리 역시 attackme가 있는 홈 디렉토리가 아닌 tmp 디렉토리에서 주소값을 가져온 것이기 때문에 주소값이 달라지게 된다.

 

※ 리눅스 버전에 따라서 환경 변수의 주소값이 바로 변수에 해당하는 값을 가리키고 있을 수도 있지만 변수 명을 가리키고 있는 경우도 있다. 예를들어 shellcode=abcd 라는 환경 변수의 주소값이 0xbffffece 라고 할 때 이 주소값을 따라가면 'a' 값이 나올 수도 있고, 변수 명인 's'값이 나올 수도 있다는 것이다. 이 때는 환경 변수의 주소값에 +@ 만큼의 byte 를 더해준 값을 사용해야 한다.

 

[그림 10]

 

실제로 환경 변수의 주소가 변수 개수에 영향을 받는지 확인하기 위해 [그림 10] 처럼 코딩을 해 보았다.

 

[그림 11]

 

컴파일 후 실행 시켜 보면 방금 [그림 4]에서 출력 되었던 0xbffffc90이 아닌 0xbffffc8e 값이 출력 되었다.

 

 

[그림 12]

[그림 13]

 

다시 공격에 사용할 텍스트 파일을 만들어서 공격을 해 보면 마찬가지로 공격에 실패하는데 이 이유는 어렵지 않게 알아낼 수 있었다. 현재 attackme 는 level15의 홈 디렉토리에 저장되어 있는 반면 환경 변수의 주소값을 출력 한 것은 tmp 디렉토리에서 가져왔기 때문이다.

 

[그림 14]

 

따라서 홈 폴더에 가서 다시 환경 변수의 주소값을 출력 해 보면 0xbffffc8e가 아닌 0xbffffc86 이 출력 되었다.

 

[그림 15]

[그림 16]

 

다시 방금 나온 주소값으로 텍스트 파일을 만들어서 공격을 진행하면 이번엔 정상적으로 공격에 성공한 것을 확인할 수 있다.

 

buf 배열에 쉘 코드를 넣고 buf 배열의 주소를 알아내서 check에 해당 주소값을 넣는 방식으로 풀 수 도 있다. 이 경우 gdb 로 main 을 바로 열 수 없기 때문에 hint 코드를 그대로 복사해서 새로 컴파일 한 뒤, 거기서 buf 배열의 주소를 출력하게 해서 check 변수에 해당 주소값을 넣는 방식으로 풀 수 있으나 환경 변수를 이용한 방법이 좀 더 간편하고 깔끔하게 문제를 풀 수 있는 방법이라 생각했다. (그리고 대부분이 buf 배열의 주소값을 찾는 방식으로 문제를 풀어 좀 다른 방식으로 풀어 보고 싶었다) 환경 변수를 가지고 시도할 때 환경 변수의 주소값이 달라질 수 있다는 것을 인지 못할 경우 처음에 시도해보았다가 포기할 수 있으나 환경 변수에 대한 내용을 좀 더 이해하면 충분히 해결할 수 있는 문제였다.

 

본인도 아직 환경 변수가 어떻게 프로그램에서 위치되고, 디렉토리와 변수에 따라서 왜 바뀌는지 정확하게 알지 못하기 때문에 이 부분에 대한 내용은 따로 찾아보고 보고서로 정리를 해 둬야겠다.

신고
댓글
댓글쓰기 폼