보안/포너블

[Pwnable] 1.Pwnable.kr 1번 - fd

Cycrypt0 2020. 4. 2. 23:00
728x90

내용 : pwnable.kr 1번문제 fd를 풀이한다. 처음 시작하는 포너블!

 

 

문제

문제에서 리눅스의 파일 디스크립터가 무엇인가에 대한 질문을 하고, 문제로 통하는 ssh 주소를 나타내주고 있다.

 

 

 

 

 

 

1. 파일 디스크립터

- 시스템으로부터 할당 받은 파일을 대표하는 0이 아닌 정수값.

- 프로세스에서 열린 파일의 목록을 관리하는 테이블의 인덱스

 

유닉스 시스템에서 프로세스가 이 파일들을 접근할 때에 파일 디스크립터(File Descriptor)라는 개념을 이용한다.

파일 디스크립터는 파이프, FIFO, 소켓, 터미널, 디바이스, 일반파일 등 종류에 상관없이 모든 열려있는 파일을 참조할때 쓴다.

파일디스크립터 

목적 

POSIX 이름 

stdio 스트림 

 0

 표준 입력

 STDIN_FILENO

 stdin

 1

 표준 출력

 STDOUT_FILENO

 stdout

 2

 표준 에러

 STDERR_FILENO

 stderr

 

표에 있는 3가지 디스크립터는 프로그램이 시작할때 셸의 디스크립터의 복사본을 상속 받고, 셸은 보통 3가지 파일 디스크립터가 언제나 열린채로 동작 한다.

프로그램에서 파일 디스크립터를 참조할때는 번호(0,1,2)를 쓸 수도 있지만 가능하면 "UNISTD.H"에 정의된 POSIX 이름을 쓰는편이 좋다..

출처: https://dev-ahn.tistory.com/96 [Developer Ahn]

 

 

 

 

 

 

 

 

ssh 접속 화면

위의 개념을 기억하고 문제로 들어가본다.

 

ls로 확인한 내부 파일의 fd.c 소스코드

 

 

 

 

 

 

fd.c 의 c코드를 열어보면, 위와 같은 소스코드를 확인할 수 있다.

또한 인증해야 하는 flag는 파일로 존재한다.

flag를 열어보려 했으나 관리자 권한이 필요해 열 수 없었다.

 

다음으로, fd.c의 내용을 살펴보면, 어떠한 조건이 충족되면 flag파일을 여는 명령(system 함수)가 보인다.

 

우선 해당 c 코드는 인자값을 받아 argv에 넣어준다.

fd 변수는 argv에 넣은 값을 정수형으로 바꿔준뒤 0x1234를 뺀 값을 안에 넣어준다.

또한 fd는 read함수의 첫번째 파라미터 값으로 들어가는데, 

 

int _read(
   int const fd, //open() 시스템 콜로 열린 파일을 가리키는 파일 지정 번호
   void * const buffer, // 파일에서 읽은 데이터를 저장할 메모리 공간
   unsigned const buffer_size //읽을 데이터의 크기(Byte 단위)
);

//반환값 : 파일 읽기 성공 : 0 보다 큰 수
//읽을 데이터 없을 시 : 0 (EOF : End Of File 파일의 끝을 만났을 때)

read 함수의 원형을 보면 위와 같습니다.

또한, fd로 들어가는 파일 지정번호는 

즉, fd 값으로 들어가야 하는것은 0이 되어야 하며, 1을 해도 실행되긴 한다.

즉, atoi한 argv에서 0x1234를 뺀 값이 0 또는 1이 되어야 하며, 

10진수로 0x1234는 4660이 된다.

 

 

 

 

 

 

 

 

즉, 

./fd 4660을 실행하면 무언가 입력할수 있게 커서가 깜빡깜빡대기 시작하는데

바로 아래에 strcmp 조건문을 보면

"LETMEWIN" 이라고 나오는 문자열과 buf를 비교한다.

 

따라서 입력창에 위의 문자열을 입력하면, 시스템함수로 flag를 호출할 수 있게 된다.

 

 

 

정답!

728x90