pwnable.kr cmd1 write up
소스코드
기능분석
먼저 main 함수에서 putenv함수로 환경변수를 설정한다. 이때 PATH가 /thankyouverymuch로 바뀌게 된다.
이후 filter 함수에 cmd1 파일을 실행할 때 넘겨준 인자가 넘어가게 되고, strstr에 의해 필터링을 하게된다.
인자에 flag, sh, tmp가 없었다면 system(넘겨준인자)를 실행한다.
익스플로잇
먼저 putenv로 path를 없앤다.
printenv로 환경변수를 확인해보면 PATH가 이렇게 설정되어있다. /usr/bin이 기본 path이기에 cat과 같은 명령어를 cat만 쳐도 실행이 되는 것이다. 하지만 path가 사라졌으니 절대 경로를 사용해야한다. 즉 인자로 /bin/원하는 명령 을 넘겨주어야 하는 것이다.
우리가 하고싶은건 flag를 읽는 방법이다.
문제를 풀때는 쉘을 획득하기 위해 노력했다.
리눅스에는 wildcard라고 문자열의 패턴을 적어서 사용하는 방법이 있다.
예를 들어 flag는 fl* 라고 하면 fl로 시작하는 모든 문자열을 의미한다.
*ag는 ag로 끝나는 문자열을 의미한다.
또한 ? 는 해당 부분에 어떤 문자열이 들어가도 된다는 의미이다.
가령 f?ag 는 flag뿐만 아니라 다양한 문자열들을 모두 의미한다.
현재 etc 디렉토리에는 다양한 명령어들이 있다. 그중 내가 원하는건
sh 함수이다.
먼저 /bin/s* 로 s로 시작하는것을 실행시키니
맨 위에 있는 sed만 실행됐다.
그렇다면 /bin/*h 로 h로 끝나는 것을 실행하니
etc 디렉토리의 알파벳 순서상 앞에 있는 dash가 실행된다.
이번엔 ? 를 이용해서 /bin/?h를 이용했다
쉘을 획득한것을 볼 수 있다. 현재 디렉토리가 어딘지 궁금해 pwd를 해보니 cmd1 디렉토리였다. 하지만 cat flag를 하니 실행되지 않았다. 그 이유는 현재 쉘이 떠있는 환경이 cmd1의 환경이니 path가 없어서 그렇다. 따라서 /bin/cat 을 이용해 flag를 출력하니 flag가 나왔다.
더 쉬운 방법
이것으로 미루어보아 쉘을 따지 않고 단지 ./cmd1 "/bin/cat fl*" 와 같이 실행하면 자동으로 플래그가 출력된다.