일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 802.3
- 802.3 이더넷
- Address Resolution Protocol
- adodb 설치
- AES 암호
- Alternatively build in profile or release modes to enable launching from the home screen
- Android Studio 몰입모드
- Android Studio 몰입모드 설정
- Android Studio 상태바 없애기
- Android Studio 자동 정렬
- android studio 자동정렬
- Android Studio 자동정렬 단축키
- Android Studio 코드 자동정렬
- Android Studio 타이틀바 없애기
- Android Studio 하단 바 없애기
- Android Studio 홈버튼 없애기
- Angler EK
- Angler EK 악성코드
- Angler EK이란
- apache2 tomcat9
- apache2 tomcat9 설치
- apache2 tomcat9 연동
- API
- apk 에러
- apk 오류
- ARP
- arp cache poisoning
- ARP Poisoning
- ARP Request
- ARP 구조
- Today
- Total
지나가는 이야기
[pwnable.kr] fd writeup | fd 문제풀이 본문
# 문제
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가 나온 것을 볼 수 있다.