fd.c source
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #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; int len = 0; len = read(fd, buf, 32); if(!strcmp("LETMEWIN\n", buf)){ printf("good job :)\n"); system("/bin/cat flag"); exit(0); } printf("learn about Linux file IO\n"); return 0; } | cs |
solve
인자 값과 0x1234 빼기 연산하여 fd(File Descriptor)를 표준입력 이 되도록하고 buf에 "LETMEWIN" 문자열이 존재하면 문제가 해결 된다.
리눅스/ 유닉스는 모든 장치를 파일로 관리한다. 일반 파일과 내부/외부 모든 장치로 파일로 취급한다.
파일로 관리하는 것을 파일 디스크립터 라고 한다.
파일 디스크립터 표준 번호는 아래 표와 같다.
Integer value | Name | <unistd.h> symbolic constant[1] | <stdio.h> file stream[2] |
---|---|---|---|
0 | Standard input | STDIN_FILENO | stdin |
1 | Standard output | STDOUT_FILENO | stdout |
2 | Standard error | STDERR_FILENO | stderr |
인자로 넘겨 받은 10진수 4660은 atoi() 함수에서는 문자열로 인식하고 int형으로 반환 한다.
fd@ubuntu:~$ ./fd 4660
LETMEWIN
good job :)
mommy! I think I know what a file descriptor is!!
Redirection 예제이다. 실제 악성코드에서 많이 사용된다.
command 1 > output.txt 표준 출력을 output.txt 파일에 저장
command 2 > output.txt 표준 에러를 output.txt 파일에 저장
command 0 < input.txt 표준 입력을 input.txt 파일에서 가져옴
command 2 >&1 표준 에러를 표준 출력 파일 디스크립터가 참조하는 곳으로 보냄
command 1 >&2 표준 출력을 표준 에러 파일 디스크립터가 참조하는 곳으로 보냄
command > /dev/null 표준 출력을 표시하지 않고 표준 에러는 표시
command > /dev/null 2>&1 표준 에러를 표준 출력으로 보내어 표준 출력과 표준 에러 모두 표시 안함
reference
- http://blog.gaerae.com/2014/10/linux-file-descriptor.html
- https://en.wikipedia.org/wiki/File_descriptor
- http://norux.me/24