2017. 6. 3. 12:28ㆍSystemHacking/System
해당 게시글의 내용은 해커스쿨-도서관 에서 다운받은 파일을 기반으로 저의 공부를 위해 작성했습니다
" 해커 지망자들이 알아야 할 Buffer Overflow Attack의 기초 " By 달고나 님의 pdf의 사진과 글을 요약 정리했습니다
< 그림 1 >
strcpy()함수를 이용해 인자로 넘어온 문자열을 buffer 문자열배열에 저장하는 소스코드입니다
[1],[2] 에서 배웠던 내용을 토대로 쉽게 이해 할 수 있을겁니다
1024byte의 버퍼공간을 쉘 생성코드와 NOP로 채우고 base pointer있는 SFP(4byte) 공간에도 NOP로 채웁니다
마지막으로 return address 가 들어있는 RET주소에 쉘 생성코드가 저장되어 있는 주소를 덮어 씌우면 쉘이 떨어져 공격 성공입니다
< 그림 2 >
해당 실행파일의 소유자 권한을 root 로 바꾸고 setuid() 설정을 걸어줍니다 ( 해당 파일 실행시 root 권한으로 실행 된다 )
하지만 해당 실행파일 내에서 setreuid함수가 없다면 해당 권한을 얻을 수 없다
=> why ? 소유자의 권한(root)을 그대로 상속받지 못했기 때문이다
=> 쉘 생성코드에 setreuid()함수의 코드를 추가시켜 주어야한다
=> 이 세가지 조건이 만족되어야 해당 파일의 권한을 그대로 상속받을 수 있다
취약점이 있는 프로그램을 생성했고 어떤 식으로 공격해야할 지도 알았습니다.
그럼 return address대신 RET주소에 넣을 쉘 코드가 저장되어 있는 주소를 알아내야 합니다
[ 방법1 ] : NOP를 이용한 고전적인 방법 ( 현재 거의 사용 x )
NOP란 ? No Operation의 약자입니다. " \x90 " 으로 표현할 수 있습니다.
CPU는 NOP를 만나게 되면 아무런 수행을 하지않고 유효한 instruction을 만날 때까지 한 바이트씩 이동합니다
쉘 코드가 저장되어 있는 주소를 정확히 알 기 힘므로 NOP를 사용해서 공격을 시도합니다
아래 그림을 보시죠
< 그림 3 >
" \x90 " 은 NOP입니다. 1028byte만큼 버퍼오버플로우 시킨 후 RET값을 변질시킵니다
RET주소에 주소X와 주소A 사이의 아무 값이나 넣습니다 그러면 " ret " 명령에 의해서 EIP에 RET주소에 있는 주소값으로 이동한다
주소X 가 저장되어있다고 가정하면, 주소X로 이동한 다음 NOP를 거쳐서 아무런 수행도 하지않고 계속 1byte씩 이동한다
결국에 쉘 생성코드가 있는 주소A에 도착하게 되고 쉘 생성코드가 실행됩니다. 공격 성공 !
[ 방법2 ] 환경변수를 이용하는 방법 ★★★
환경변수는 메모리 어딘가에 항상 저장되어 있다. 우리는 환경변수를 포인터를 이용해서 사용할 수 있다
따라서 환경변수에 쉘 생성코드를 넣어주고 그 주소를 알아내어 사용하면 됩니다
환경변수에 쉘생성코드를 넣는 방법과 환경 변수가 위치한 주소를 알아내는 좋은 프로그램이 있습니다.
바로 에그쉘이라고 불리우는 프로그램입니다 ㅡ 그림 4,5 참고
#vi eggshell.c
< 그림 4 >
< 그림 5 >
해당 소스파일을 컴파일 한 후 실행시키면 ESP주소가 출력되고 쉘이 떨어집니다
$gcc -o eggshell eggshell.c
$./eggshell
< 그림 6 >
에그쉘에서 사용한 get_esp()함수는 어셈블리 코드를 이용하여 ESP레지스터가 가르키는 곳의 주소를 EAX레지스터에 넣는 역할을 한다
이것만으로 EAX레지스터의 값이 리턴된다. 에그쉘의 키 포인트는 " 대부분의 프로그램들의 스텍 시작점은 같다 " 이다
어떤 함수가 실행될 때 이전 함수의 base pointer를 저장하고 스텍 포인터가 main함수의 base pointer가 된다
그리고 실행한 함수의 지역변수들이 스택에 쌓이기 시작한다. 함수가 종료되면 base pointer로 복귀된다.
이런 방식으로 같은 쉘 환경에서 프로그램이 실행되면 main함수에서 만나는 스텍포인터는 같을 수 밖에 없다
따라서 공격자는 스텍 포인터의 주소값을 알아내어 거기서 부터 return address를 유추하는 것이다
즉, 에그쉘(egg파일)을 실행 결과 출력된 stack pointer값은 EGG라는 환경변수가 위치한 범위 내의 어딘가를 가리키고 있다는 것이다
그림으로 표현하면 이해하기 쉽습니다 아래그림을 참고하세요 ㅡ 그림 7
< 그림 7 >
에그쉘을 실행하기 전에는 ebp와 esp 가 주소 " 0xbfffffa88 " 에 존재하고 있음이 보입니다
에그쉘을 실행한 후에는 0x800 만큼 주소가 아래로 내려갔다. ( 0x800 == 2048byte ) 이것은 egg.c에서 egg배열의 크기이다.
해당 크기만큼 ebp와 esp가 내려감을 확인 할 수있다.
에그쉘 코드(egg.c) 를 작성 할 때 esp주소를 출력하는 함수는 EGG를 환경변수에 등록하기 전이다
따라서 우리는 egg실행전 esp주소를 알 수 있고 이 주소는 환경변수 EGG가 위치하는 범위 내의 어딘가이다
EGG 안에는 많은 NOP가 들어있기때문에 esp가 정확한 환경변수 EGG의 주소가 아닐지라도 EGG 안의 NOP들에 의해서 instruction pointer가 흘러서
쉘 생성 코드 시작점까지 도착할 수 있게 된다.
환경변수가 잘 등록되어있는지도 확인해봅시다
< 그림 8 >
환경변수 EGG가 제대로 들어가있음이 확인됩니다. 그러면 이제 취약 프로그램 vul 에서 어느 지점에 return address가 있는지 확인합시다
그리고 해당 지점에 stack pointer의 값을 넣으면 공격은 성공됩니다
" vul " 프로그램의 main()함수를 디스어셈블해보면 알 수 있습니다
< 그림 9 >
main()함수의 시작부분에서 지역변수 공간을 1040byte만큼 할당해주는 것을 알 수 있습니다
buffer의 크기는 1024 이고 dummy가 16byte만큼을 차지하고 있습니다
따라서 1040byte만큼의 크기와 SFP(base pointer)의 4byte를 합한 1044byte를 버퍼오버플로우 시키면 return address가 위치한
RET 의 공간에 도달하게 됩니다. 해당 공간에 에그쉘프로그램으로 구한 환경변수 EGG의 주소를 덮어 씌우면됩니다
그리고 프로그램이 실행되면 " ret " 명령에 의해 EGG의 주소로 이동해서 해당주소에 있는 쉘생성코드를 실행시킬겁니다
지금까지 이론적으로는 틀린 부분은 없습니다. 하지만 직접 실행하였더니 제대로된 결과가 나오지 않았습니다....
( 작성한 에그쉘과 쉘 실행코드에는 아무런 이상없이 작동합니다. " vul " 프로그램의 주소와 관련되서 이상이 있는거 같다 )
< 그림 10 >
구글링을 하다보니 에그쉘로 구한 EGG의 주소와 쉘에서 출력한 결과가 다르다는 문서가 있었다
" getAddr.c " 파일을 작성해서 출력해보았더니 서로 주소가 달랐다. ( 이유는 아직 모르겟다... )
두 주소를 모두 공격지점에 넣어보아도 세그멘테이션오류가 나왔다.
세그멘테이션오류가 나오는 이유는 RET지점에 존재하지 않는 주소가 있기 때문에 발생한 결과이다
하지만 EGG변수의 주소 그대로 넣엇는데 왜 이런결과가 나오는지는 모르겠다..
제 서버에서 주소값들이 0x000000000400554 이런식으로 이상하게 나오는데 아마 여기에 이유가 있는것같습니다.
FTZ서버문제풀이에서 다시한번 해당 에그쉘 코드를 사용해서 문제를 풀어보겠습니다
버퍼 오버 플로우의 이론은 여기까지입니다. 실제 결과는 좋지 않았지만 이론은 틀린 부분없이 잘 설명해놓았습니다.
해당 공격이 왜 실패 되었는지는 더 공부해가면서 수정하겠습니다.
에그쉘코드는 구글링하면 바로나옵니다. ( 복사해서 붙여넣으면 바로실행 가능함 )
==================================================
왜 세그멘테이션오류가 나왔는지 알아냈습니다!! 구글링을해서 찾아보니 에그쉘은 거짓말쟁이였습니다
에그쉘이 알려주는 쉘코드의 주소는 진짜가 아닙니다. 자세한 내용은 [4]번 문서에서 제대로 설명해드리겠습니다
[4] 환경변수를 이용한 버퍼 오버플로우 공격 << Click !!
'SystemHacking > System' 카테고리의 다른 글
[6] Format String Bug [FSB] (0) | 2017.06.08 |
---|---|
[5] Heap Buffer Overflow ( Heap기반의 버퍼오버플로우 ) (0) | 2017.06.07 |
[4] 환경변수를 이용한 버퍼 오버플로우 공격 ( 에그쉘) (1) | 2017.06.05 |
[2] 쉘 코드 작성하기 (0) | 2017.06.02 |
[1] BufferOverflow Attack의 기초 ( 스택기반의 버퍼오버플로우 ) (0) | 2017.06.01 |