자 이번 문제부터 본격적인 BOF문제이다
소스코드를 보니 버퍼는 256바이트이며 gets함수를 사용한다
gets함수도 strcpy와 같이 길이를 재지 않고 복사를한다
아 우선 BOF에 대해 설명하자면
BOF란 Buffer OverFlow의 약자로 버퍼가 넘치는 데이터를 집어 넣어 쉘을 얻는 공격기법중 하나이다
시스템 해킹 공격기법중의 기초라고도 할 수 있으며 BOF의 공격기법 또한 다양하다
우리는 가장 기초적인 BOF공격기법과 환경변수를 이용한 공격기법, 그리고 RTL이라는 공격기법을 통해 쉘을 얻을 것이다
아 참고로 기본적인 RET SFP이런것들은 알고 있다고 가정하고 설명하겠다
우선 스택을 파악해보자
우선 스택에 0x108, 즉 264가 할당이 됐다
버퍼가 256바이트인데 264가 할당이 됐다, 더미가 있다는 뜻이다
더미가 버퍼 앞에있는지 뒤에있는지 알 수 없다 우선 값을 넣어보고 알아보자
우선 저기 빨간 부분은 버퍼다 총 256바이트이다 그리고 아까 말했듯이 264바이트가 할당되었는데 264-256은 8이다 8바이트가 더미로 잡혀있으며 노란색이다
그리고 초록색은 SFP이다 그리고 그 다음 파란색은 RET이다
그리고 남색은 argc이다. 보라색은 argv이다 이 두 개는 main함수의 매개변수들이다
그리고 마지막 흰색은 env 환경변수들이다
자 스택을 그려보면
이렇게 된다
우리는 Buffer(256) + Dummy(8) + SFP(4) 에다가 쉘코드와 NOP를 집어넣고 RET에 쉘코드 시작주소를 넣을것이다
아 여기서 NOP을 집어넣는데 NOP이란 아무 일도 하지 않는다는 뜻이란 명령어 같은 것이다 이것을 많이 깔아서 쉘코드에 쉽게 다가가는 것을 NOP슬라이딩이라고 한다.
스크립트 언어로 쉘코드와 NOP로 268바이트를 덮고 RET에 쉘코드 시작주소를 넣을 것이다
페이로드는 NOP(100)+shellcode(25)+NOP(143)+RET이렇게 된다
공격해보자
세그멘테이션 폴트가 뜬다
레드햇 9.0부터는 메모리 보호기법중 하나인 ASLR이 적용이 된다 그래서 이런방식으로 뚫기란 매우 힘들다
그럼 환경변수를 이용한 공격을 해보자
먼저 쉘코드를 집어넣을 환경변수를 만들자
그리고 이 환경변수가 시스템 어디에 있는지 알려줄 간단한 소스를 코딩한다
사용법은 다음과 같다
./getenvaddr 환경변수이름 프로그램경로
우리가 사용할 환경변수이름은 SHELLCODE이고
프로그램경로는 attackme이니 이렇게 사용하면 된다
자 그럼 이제 쉘코드가 있는 곳도 알았고 RET직전까지 아무거나 덮어쓰고 RET에 저 주소를 입력하면 RET의 jmp eip명령어로 인해 쉘코드가있는곳으로 점프할 것이고 쉘코드를 실행할것이다
이번 공격에는 NOP같은게 쓰이지 않는다 왜냐하면 이미 쉘코드의 주소를 정확히 알기 때문이다
공격해보자
공격이 성공했다
그리고 다른 공격방법 하나를 더 소개하려 한다
RTL, Return To Libc라는 공격인데 리눅스에 존재하는 공유 라이브러리 개념을 이용한 기법이다
예를 들자면 printf 함수를 사용할 때 printf를 포함한 내장 라이브러리인 libc가 libc 영역에 적재되게 된다
이때 printf 함수만 libc 영역에 적재되는 것이 아니라 libcso에 모든 함수가 이 영역에 적재되게 된다
따라서 함수를 사용하지 않더라도 모든 함수가 올라오고 이 함수들을 자유롭게 사용할 수 있게 된다
이러한 원리를 이용해 RET에 내장함수의 주소로 변경해 공격하는 기법을 RTL이라 한다
우선 공격하기 전에 ret명령으로 실행하는 함수와 함수의 인자 사용에 대해 알아보려 한다
ret명령은 현재 esp가 가리키는 곳에서 값을 꺼내 eip로 설정하는데 ret에 함수의 주소가 있다면 함수를 실행하게 된다
그럼 call명령어에 의한 함수 호출과 ret명령어에 의한 함수 호출의 차이는 무엇일까?
call명령어의 경우 ret를 스택에 저장하고 함수를 호출한다
호출한 함수가 끝나고 함수내에서 ret를 실행하면 esp+4한부분부터 실행흐름을 계속하게 된다
그럼 공격을 해보자
페이로드는 다음과 같다
쓰레기값(268)+system함수주소(4)+exit함수주소(4)+/bin/sh가있는주소(4) 이렇게 집어넣을 것이다
아 그리고 저렇게 system 함수 뒤에 다른함수도 넣는 까닭은 system(“/bin/sh”)이것을 실행하기 위함인데 exit가 들어가는 이유는 system함수의 리턴주소에 exit함수를 넣은 것이다.
자 이제 각 함수들의 주소들을 알아보자
이제 /bin/sh의 주소를 알아보기 위해 다음을 코딩한다
자 이제 모든 주소를 알았다 공격해보자
Level12를 클리어했다
Phantom@TeamH4C