flag를 찾아내야한다.
ssh로 접속하자.
#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;
}
buf가 32바이트 만큼 전역변수로 선언이 되어 있다.
main
int argc: main 함수에 전달되는 인자의 개수이다. 기본적으로 실행파일을 실행을 하게 되면, 인자의 개수는 1개이다.(실행파일 하나만 해당)
char* argv[]: main 함수에 전달되는 실질적인 정보들이다. 문자열로 전달되며, 구분자는 (\0)이고, 기본적으로 실행파일을 실행하게 되면 argv[0]은 실행파일 경로가 들어가게된다.
char* envp[]: 프로그램의 환경 변수값을 저장하고 있다.
if(argc < 2):
인자를 두 개 이상 전달해야 이 if문을 통과 할 수 있다. 1개라면 "pass argv[1] a number"을 출력한다.
int fd = atoi(argv[1]) - 0x1234
atoi()란 10진수 문자열을 정수 형태로 변환해 준다.
예를 들어, 인자값으로 103을 입력했을 때, 실행 파일에는 '103'인 문자열로 들어간다.
atoi로 변환을 하게 되면 103인 정수가 된다.
len = read(fd, buf, 32);
read로 buf에 32바이트 만큼 입력받는다.
그 전에 fd 값은 위에서 정해진다.
fd가 stdin, 즉 입력 read syscall 번호는 0이므로, fd 값은 0이 되어야 buf에 입력이 가능하다.
표준입력: stdin - 0
표준출력: stdout - 1
표준에러: stderr - 2
if(!strcmp("LETMEWIN\n", buf)):
이 if문 조건에 충족하지 않으면, "learn about Linux file IO"를 출력하고 프로그램을 종료한다.
이 if문 조건에 충족하면, "good job : "을 출력하고,
system 함수를 호출 해, flag의 값을 출력할 수 있게된다. 즉, 답을 찾을 수 있다.
조건을 보면 "LETMEWIN\n"과 buf의 값을 strcmp로 비교를 한다.
strcmp 함수는 값이 같으면 0, 다르면 1을 반환한다.
하지만, ! 비트 반전 기호가 있으므로, 같으면 1, 다르면 0을 반환한다.
따라서 buf의 값을 "LETMEWIN\n"을 입력하게 되면, 조건에 충족하여 flag를 알 수 있게 된다.
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);
if(!strcmp("LETMEWIN\n", buf)){
결론적으로 이 부분을 통과하면 flag를, 즉, 답을 얻을 수 있다.
argv[1]을 0x1234, 10진수로 4660로 넘겨주면 fd값이 0이 된다.
구한 fd값으로 read를 통해 buf에 입력할 수 있다.
조건에 맞춰, 즉, buf의 값이 "LETMEWIN\n"을 입력해 준다.
argv[1] 값으로 4660 넘겨줌으로써 입력이 가능해짐
LETMEWIN을 입력하고 \n, 즉 엔터키를 누르면,
flag를 획득한 모습을 확인할 수 있다.
http://pwnable.kr/play.php (문제 출처)