WARGAME/FTZ [system] (20) 썸네일형 리스트형 ftz level 20 [level20] 이문제는 setreuid() 도 있고 간단해 보이지만, bleh 는 80 바이트, 그러나 입력으로 받는 크기는 79 바이트로 오버플로우가 가능하지 않아보인다. 그러나 잘 보면, printf() 에 형식 지정자가 없이 출력을 하는, 즉 포맷 스트링 버그를 발견할 수 있다. *** 포맷 스트링 버그 (Format String bug, FSB) : 버퍼 오버플로우 해킹 기법의 한종류로, 사용자의 입력에 의해서 프로그램의 흐름을 변경시킬수있는 취약점 : 만일 입력하는 문자열에 서식 문자가 들어가게 되면, 스택의 다음 4바이트를 출력하는 오류가 발생한다. : ex. 입력한 서식 문자가 %x 라면 다음 4바이트를 16진수로 출력 따라서 만약 aaaa%x 등을 입력하면? 이렇게 일반 문자는 정상적으로 출력이 되지만,.. ftz level 19 [level19] 이번에는 너무 짧아서 놀랐다. 너무 간단해보이는데..? ㅎㅎ 바로 쉘코드 환경변수에 올리고 오버플로우 시켜 ret 자리에 환경 변수 주소가 오도록 빨리빨리 진행해보자. 그러나 이번 문제에서는 setreuid 로 권한 상승을 해주는 부분이 없기 때문에 setreuid() 를 포함하는 쉘코드를 환경변수로 등록해야한다. 4 참고 https://security-nanglam.tistory.com/117 먼저 디버깅부터 해서 buf 의 시작주소를 기반으로 얼만큼 오버라이딩 시키면 될지부터 확인하자. main+9 에 ebp-40 위치가 buf 의 위치. 스택을 그려보자면 이런 형태. 암튼 페이로드는 "a"*44 + 환경변수 주소 가 될 것이다. getenv.c 생성 후 컴파일, 환경 변수 주소 획득 페이로드 입력하.. ftz level 18 [level18] cat hint ! 너무 길어서 깜짝 놀랐다. 천천히 해석을 해보자면, 우선 쉘은 shellout()에 들어있으니 shellout() 을 실행하면 되는 것 같고, check 가 0xdeadbeef 면 shellout() 을 호출하므로, check 가 0cdeadbeef 가 되도록 하면 될 것 같다. 그리고 중간에 보이는 fd_set 은 파일 디스크립터 구조체를 의미한다. FD_ZERO 는 fd_set 으로 선언된 변수인 fds 를 초기화 할때 쓰이는 함수이다. 한마디로 이 소스에서는 STDID_FILENO 등이 인자로 사용된걸로 보아 그냥 사용자의 입력을 받는 구조체 정도로 이해하면 될 것 같다. 사용자의 입력에서 1바이트만 x 에 넣어 \r \n 0x08 이 아닌 경우 stiring[count] 에 x.. ftz level 17 [level17] 이번 문제는 그냥 거의 level16 이랑 똑같아보인다. 다른 점은 shell() 함수가 없다는 것. 앞선 문제에서 shell() 이 배시 쉘을 실행시키는 함수였기 때문에 여기서는 환경변수에 쉘코드를 올려두고 환경변수의 주소가 call() 의 위치에 오도록 오버플로우 하면 된다. 그럼 전에도 했듯이 attackme 를 복사해 ./tmp 아래에 두고 디버깅으로 오버플로우 시켜야할 크기를 확인해보자. level16 이랑 너무 똑같아서 소름 끼칠 정도이다. 그래도 간단히 정리하자면, buf 는 esp-56 위치에, call() 함수는 esp-16 위치에 존재한다. 즉, buf 에 입력으로 40 바이트를 채우고, call() 가 함수를 호출하는 자리에 환경변수 주소를 넣자. 넉넉히 nop 15바이트로 시작하는 .. ftz level 16 [level16] 역시 bof 로 보이고, fgets 함수의 취약점을 이용하면 될 것 같다. 20 바이트 크기의 buf 를 할당하고, 사용자로부터 48바이트 만큼의 입력을 받는다. 그리고 printit 의 주소를 출력해주는 실행파일로 보인다. 우리는 위에 보이다시피 shell() 의 주소가 call() 되도록 만들면 쉘을 딸 수 있을 것이다. 하도 많이해서 익숙해진 gdb 로 buf 와 call() 의 거리를 확인해보자. 스택까지 그려보자. 손으로 써서 알아보기 어렵지만, 대충 esp-56(0x38) 이 buf 의 시작주소, esp-16 이 call() 의 시작주소가 된다는 뜻. 즉, esp-16 에 들어간 주소 값이 printit() 의 주소가 된다는 뜻이다. 이자리에 shell() 의 시작주소를 넣고 싶은거니까, sh.. ftz level 15 [level15] 이 문제는 level14 와 정말 비슷해보이지만 차이는 check 라는 포인터 변수가 가리키는 주소의 값이 0xdeadbeed 가 되도록 해야한다. 귀찮으니까 attackme 를 level14/tmp 위치에 복사 시킨후 디버깅해보자. 앞 문제에서 본 결과와 같은 것을 볼 수 있다. 오버플로우 방법은 여러가지가 있을 수 있지만 내가 생각해낸 방법은 바로 check 포인터 자리에 deadbeef 문자열이 들어있는 주소가 오도록 오버플로우 시키는 방법이다. 먼저 strcmp 을 하는 부분에 브포를 걸고 실행시켜서 deadbeef 문자열이 들어있는 곳의 주소를 찾아내자. eip 레지스터(다음 명령어 ) 의 주소값을 출력하기 위해 넉넉히 32개의 16진수로 출력을 해주면, deadbeef 문자열이 담긴 주소 0x.. ftz level 14 [level14] 힌트를 살펴보니, level9에서 "go" 가 원하는 곳에 오도록 하는 문제와 비슷해보인다. 다른 점은 check 가 0xdeadbeef 여야 한다는 것? 입력은 buf 에 버퍼 크기는 20 byte. 사용자로부터 45byte까지 입력 받을 수 있고, check 는 어디에 위치해 있는지 디버깅을 통해 확인해보자. 작성 후 컴파일, 디버깅. 스택으로 확인해보면, buf 는 ebp 보다 56 바이트 위 할당 cmp로 비교되는 check 은 ebp 보다 16 바이트 위 할당 따라서 둘의 차이는 40 바이트가 될 것이다. 페이로드는 40 바이트 만큼 오버플로우 후 0xdeadbeef 를 입력하면 되는 것. (python -c 'print "a"*40 + "\xef\xbe\xad\xde"';cat ) | /hom.. ftz level 13 [level13] 이번에도.. 딱봐도 오버플로우다. 살펴보면 왠지 스택은 low buf i SFP RET high 이런 형태일 것 같고, 아마 if 문에서 i 값이 1234567 인지 확인한 후 맞아야 종료되지 않는 걸로 보아 buf 에 값을 오버플로우 시켜 i 자리에 1234567 이 들어가도록 하는 것 같다. 정확한 바이트 수를 알아내기 위해 /tmp 로 이동 후 똑같이 소스파일 생성, 컴파일, 디버깅을 해보자. 처음 esp 에서 0x418 (1048) 만큼 공간을 할당해주는 부분이 보이고, ebp -12 위치에 0x1234567 인 i 가 할당되어 있는 것을 볼 수 있다. 이를 참고해서 간단하게 스택을 그려보자면, 이런식으로 되는 셈이다. buf[1024] + dummy[12] + i[4] + dummy[8] = 1.. 이전 1 2 3 다음