pwnable.kr (fd)
ftz 랑 LOB를 끝내고 다음 할 것을 찾다가 잊고있었던 포너블.kr을 꺼내본다..
문제이름이 fd 이다. 우선 제시해준 ssh 에 접속하도록 하자.
접속하면 다음과 같은 화면이 나온다.
ls 명령어를 이용해 fd, fd.c, flag 파일이 존재하는것을 확인 할 수 있다.
당연하겠지만 flag 를 읽으려고 하였더너 권한 거부가 뜬다.....
다른 파일을 먼저 확인해보자.
fd.c 라는 파일을 읽어보았다.
집중할 부분에 빨간 박스를 처놓았다.
실행 과정을 보자.
- 파일을 실행할 때 인자를 입력받는다.
- 입력받은 인자를 숫자로 바꾼뒤 0x1234를 빼는 연산을 해준다.
- read함수에 연산을 마친 fd 변수가 들어간다.
- fd 값의 따른 결과 값을 buf에 32byte만큼 저장한다.
- buf값과 "LETMEIN\n"의 값이 같으면 /bin/cat flag 명령어를 실행한다.
대충 이 정도의 과정을 거친다.
그럼 여기서 필요한 지식에 대해 알아보자.
fd (file descriptor)
사용자가 파일을 사용하기위해 핸들을 얻어내는 것이다.
우리가 알아야 할 점은 리눅스, 유닉스 시스템에서는 일반적으로 0, 1, 2번 fd는 특수한 목적으로 사용된다는 점이다.
각각의 값들의 해당하는 내용은 아래 표와 같다.
- 0번 : Standard input 표준 입력
- 1번 : Standard output 표준 출력
- 2번 : Standard error 표준 오류
즉 위 read 함수 fd 값이 0이 된다면 우리가 원하는 내용을 buf에 쓸 수 있게 된다.
문제 풀이
실행 과정
- 파일을 실행할 때 인자를 입력받는다.
- 입력받은 인자를 숫자로 바꾼뒤 0x1234를 빼는 연산을 해준다.
- read함수에 연산을 마친 fd 변수가 들어간다. ==⇒ fd 값을 0으로 해주어야 한다.
- fd 값의 따른 결과 값을 buf에 32byte만큼 저장한다.
- buf값과 "LETMEIN\n"의 값이 같으면 /bin/cat flag 명령어를 실행한다.
실행 과정은 위에서도 말했듯이 다음과 같다.
따라서 fd 값을 0으로 해주어 "LETMEIN" 이라는 문자열을 buf에 저장하기만 하면 된다.
fd 값을 0으로 해주기 위해선 첫번째 인자인 argv[1]에서 0x1234를 빼는 연산이 있기 때문에 argv[1]에 0x1234를 입력해야 한다.
0x1234는 십진수로 4660이기 때문에 4660을 인자로 넘겨주면 된다.
그 후 입력 대기 상태가 될 텐데 if문을 통과하기 위해 LETMEIN을 입력해주면 플래그를 뱉어준다.
Question
if 문 안에 strcmp에 !가 붙어있길래 !연산은 0을 1로 1을 0으로 바꿔주는 연산인데 왜 붙어있는지가 궁금했다.
strcmp 반환값에 대해 찾아본 결과 strcmp는 첫번째 인자와 두번째 인자를 비교하여 ascii코드값의 차이값을 뱉어내는 것을 알 수 있었다.
따라서 if 문을 통과하기 위해서는 참 즉 0이 아닌 다른 값이 와야하는데 strcmp는 첫번째 인자와 두번째 인자의 값이 같을 때 0을 뱉어내니 이 값을 참으로 만들어주기 위해 사용한 것임을 알 수 있었다.