시스템 해킹 1도 몰라서 해설이 구구절절할 수 있다.
fd (file descripter)
리눅스는 모든 것을 파일로 취급한다. 파일을 지칭하는 번호이다.
기본 fd로는 표준 입력 0, 표준 출력 1, 표준 에러 2가 있고 3부터 파일 오픈 or 소켓 생성시 부여된다.
더 자세한 정보: https://code4human.tistory.com/123
환경: utm arm64 리눅스 22.04
1. ssh fd@pwnable.kr -p2222 (pw:guest) 로 들어가본다
내가 누구인지 확인하고, flag 파일을 찾는다.
flag 파일은 fd_pwn 사람이거나 root 그룹만 read가 가능하다.
읽으려고 할 경우에 사고가 발생한다..
fd 파일 허가권을 보니 r-s가 있다.
s : setuid 비트는 일반 유저가 파일 실행시 파일 소유자 권한으로 실행된다. (일반 유저들이 파일을 열 수 있도록 일시적으로 부여)
setuid가 필요한 이유: setuid 와 setgid 가 필요한 이유는 일반 사용자가 변경할 수 없는 파일이지만 변경이 필요한 경우가 있어서 입니다.
예로 사용자의 암호를 담고있는 /etc/shadow 파일은 root 만 읽을수 있고 수정은 불가하지만 사용자가 암호를 변경할 경우 /etc/shadow 파일이 변경되어야 합니다.
그래서 암호를 변경하는 /usr/bin/passwd 는 setuid 비트가 붙어 있으며 이 비트가 있으면 실행시 파일의 소유자 권한으로 전환되므로 root 권한을 갖게 되어 /etc/shadow 파일에 변경된 암호를 기록할 수 있게 됩니다.
출처: https://www.lesstif.com/lpt/linux-setuid-setgid-sticky-bit-93127311.html
./fd 실행하면 숫자가 필요하다고 한다. fd.c 파일을 살펴보자.
궁금한 점: ./와 cat 명령어 실행 차이? (cat fd 실행시에는 저 문구가 나오지 않았다.)
코드
argc (count) : 명령행 옵션의 개수 (명령어 자체도 포함됨)
argv (value) : 명령행 옵션의 문자열 실제 저장되는 배열
argc가 1이면 명령어만 입력하고 그 뒤 옵션을 지정하지 않았음(인자가 없음)을 의미한다.
./fd 와 같음
./fd 1234 : argc(개수)는 2, argv[1]은 1234
참고: https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ygszzang11&logNo=50178777730
len = read(fd,buf,32);
Read 함수
파일을 읽는 함수, 정상 실행시에는 읽어들인 바이트 수 반환(그렇지않으면 -1)
인자 : 파일 디스크립터, 버퍼, 버퍼 크기
strcmp 함수
두 문자열을 비교하여 같으면 0, str1> str2이면 양수, str1 < str2이면 음수 반환
코드 해석
1. 옵션이 없을때 메세지 출력 후 반환
2. fd는 인자에 따라 달라지고 (인자에 0x1234 뺀 값) buf의 값이 LETMEWIN이면 flag가 출력된다.
3. 그렇지 않으면 learn about Linux file IO (힌트 출력)
buf에는 아무런 값이 없으므로 buf에 값을 입력하기 -> fd:0(표준 입력) 만들기
0x1234 = 4660이다.
질문
fd 0,1,2는 표준 입력, 표준 출력, 표준 에러인데, 파일 디스크립터와의 연관성이 무엇인가요?
답변
유닉스에서 모든 것은 파일입니다. 유닉스 시스템에서 프로세스가 이 파일들을 접근할 때 File Descriptor 개념을 이용합니다.
프로세스가 실행중인 파일을 Open하면 커널은 해당 프로세스의 파일 디스크립터 숫자 중에 사용하지 않는 가장 작은 값을 할당합니다.
각 파일 디스크립터는 어떤 정수(Inter)값이고, 그것은 어떤 하나의 open file과 연결되어 있습니다.
프로세스들은 이러한 파일 디스크립터를 이용해 데이터를 처리합니다.
데이터는 바이트를 한 곳에서 다른 곳으로 전송하는 스트림(Stream)을 통해 흐릅니다.
3가지의 기본 입/출력 스트림(표준 입력, 표준 출력, 표준 에러)들은 기본적으로 각자 특정한 파일 디스크립터를 가지고 있습니다.
stdin=0, stdout=1, stderr=2
터미널로 데이터를 출력할 수 있는 스트림은 기본적으로 stdout과 stderr가 있습니다.
정리하자면 리눅스 / 유닉스는 모든 장치들을 파일로 관리하는데, 일반 파일과 내부/외부 모든 장치도 파일로 취급합니다. 모든 열려있는 파일을 참조할때 사용하는 것이 파일 디스크립터입니다.
이때 표준 파일 디스크립터로써 사용되는 0(표준 입력), 1(표준 출력), 2(표준 에러)는 모든 유닉스/리눅스 쉘들이 항상 열어놓고, 프로그램이 시작될때 해당 프로그램에 연결시켜주는 역할을 합니다.
위 3개를 제외한 파일 디스크립터는 별도로 파일 소켓등의 생성 과정을 거친 뒤에야 파일 디스크립터 번호가 할당됩니다.
즉, 모든 장치들을 파일로 관리하므로 파일 입출력에 쓰이는 3가지 디스크립터를 기본으로 설정해 둔 것입니다.
https://dev-ahn.tistory.com/96
http://www.ktword.co.kr/test/view/view.php?m_temp1=2362
'보안공부 > 시스템 해킹' 카테고리의 다른 글
pwnable 3번: bof (2) | 2023.01.30 |
---|---|
pwnable 2번: collision (0) | 2023.01.30 |