관리 메뉴

지나가는 이야기

[pwnable.kr] fd writeup | fd 문제풀이 본문

CTF : Capture The Flag/pwnable.kr

[pwnable.kr] fd writeup | fd 문제풀이

지나가는 이야기 2023. 11. 24. 22:15
728x90
반응형

 

 

# 문제

fd 문제의 경우 ssh를 통해 접속하라고 되어 있어 ssh를 이용하여 접속한다.

 

위 사진은 해당 서버에 접속한 모습으로 리눅스 시스템으로 보인다.

 

현재 상태를 보기 위해 ls -al 명령어를 사용하니 fd, fd.c, flag 이렇게 3개의 파일이 있으며 특히 flag의 내용을 확인하면 되는 문제로 보인다. 파일 내용을 확인해 보니 권한이 없는 것으로 보여 현재 사용자 및 그룹을 확인해 보았다.

결국 확인할 수 있는 파일의 내용은 fd.c이고, 해당 파일을 분석하여 flag를 얻는 것으로 보인다.

 

 

# 풀이

위 사진은 fd.c의 내용으로 c언어로 작성된 것으로 보여 분석하여 flag를 얻어야 한다.

 

## 소스코드 분석

본격적인 소스코드 분석을 하기 전 main() 함수의 인자값에 대해 알아야 한다. 현재 코드에서는 총 3개의 인자 값이 있으며 각각의 설명은 아래와 같다.

인자 설명
int argc 프로그램 실행 시 인자의 개수
char* argv[] 프로그램 실행 시 인자의 백터
char* envp[] 환경 변수

 

program hello 3 hi

위와 같이 실행했을 때

argc : 3

argc[0] : "program\0"

argc[1] : "hello\0"

argc[2] : "3\0"

argc[3] : "hi\0"

즉 인자에 대한 예시는 위와 같다.

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
	if(argc<2){				// 인자 값을 안주면 프로그램 즉시 종료
		printf("pass argv[1] a number\n");
		return 0;
	}
	int fd = atoi( argv[1] ) - 0x1234;	// 입력한 문자를 정수로 변환한 후 0x1234를 뺌
	int len = 0;
	len = read(fd, buf, 32);		// 키보드로 입력 받은 값을 buf에 저장
	if(!strcmp("LETMEWIN\n", buf)){		// 입력 받은 값과 비교
		printf("good job :)\n");
		system("/bin/cat flag");
		exit(0);
	}
	printf("learn about Linux file IO\n");
	return 0;

}

소스코드를 대략적으로 분석하면 위와 같으며 이제 상세하게 분석하도록 한다.

 

 

 

 

if(argc<2){	// 인자 값이 없을 경우 실행
	printf("pass argv[1] a number\n");
	return 0;
}

위 부분은 프로그램 실행 시 인자 값을 넣지 않았을 때의 실행하는 구문으로 첫 번째 인자 값은 숫자로 입력하라는 문구가 나온다. 그렇다고 아무 숫자나 입력해도 정상 동작 안 하는 것을 볼 수 있어 다음 코드를 분석한다.

 

int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);

atoi() 함수의 경우 문자열을 정수로 변환해 준다. 그리고 read()의 경우 보통 파일을 읽을 때 사용하는 것으로 알고 있으나 키보드 입력 도 받을 수 있다.

read((int fd, void *buf, size_t nbytes)

fd : 파일 디스크립터(File Descriptor)

buf : 저장시킬 곳

nbytes : 저장할 크기

read() 함수의 경우 위와 같으며 여기서 중요한 것이 바로 파일 디스크립터이다.

 


### File Descriptor

파일 디스크립터는 입/출력 및 에러에 사용되는 표현으로 0~2까지의 정수로 이루어진다. 즉 이문제에서는 fd의 값을 0으로 만들어 키보드 입력을 받으라는 것이다.


 

fd값이 0이 되기 위해서는 atoi() 함수의 결과가 0x1234의 값으로 만들어 줘야 한다. 0x1234를 10진수로 변환하면 4660이 나오기 때문에 프로그램 실행 시 4660을 넣게 되면 키보드 입력을 할 수 있다.

 

위와 같이 키보드 입력을 받을 수 있는 것을 확인했다.

 

if(!strcmp("LETMEWIN\n", buf)){
    printf("good job :)\n");
    system("/bin/cat flag");
    exit(0);
}

위 조건문을 해결해야 FLAG를 획득할 수 있어 보인다. 

strcmp() 함수의 경우 인자 값을 비교하여 서로 같은지 다른지 알려주는 함수로

 

strcmp(문자1, 문자2)
문자1 과 문자2를 서로 비교하여
서로 같으면 0을 리턴
서로 다르면 1을 리턴

위와 같이 동작한다. 그리고 !로 인해 이전 결과가 뒤집히므로 즉 서로 같은 문자를 넣어야 해당 조건문이 True가 되어 조건문을 실행할 수 있다.

 

위와 같이 FLAG가 나온 것을 볼 수  있다.

 

 

 

728x90
반응형
Comments