[4pt]input

Pwnable.kr 2015. 8. 15. 20:05
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char* argv[], char* envp[]){	
		printf("Welcome to pwnable.kr\n");
		printf("Let's see if you know how to give input to program\n");
		printf("Just give me correct inputs then you will get the flag :)\n");

		// argv
		if(argc != 100) return 0;
		if(strcmp(argv['A'],"\x00")) return 0;
		if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
		printf("Stage 1 clear!\n");

		// stdio
		char buf[4];
		read(0, buf, 4);
		if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
		read(2, buf, 4);
		if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;
		printf("Stage 2 clear!\n");

		// env
		if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
		printf("Stage 3 clear!\n");

		// file
		FILE* fp = fopen("\x0a", "r");
		if(!fp) return 0;
		if( fread(buf, 4, 1, fp)!=1 ) return 0;
		if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;
		fclose(fp);
		printf("Stage 4 clear!\n");

		// network
		int sd, cd;
		struct sockaddr_in saddr, caddr;
		sd = socket(AF_INET, SOCK_STREAM, 0);
		if(sd == -1){
				printf("socket error, tell admin\n");
				return 0;
		}
		saddr.sin_family = AF_INET;
		saddr.sin_addr.s_addr = INADDR_ANY;
		saddr.sin_port = htons( atoi(argv['C']) );
		if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
				printf("bind error, use another port\n");
				return 1;
		}
		listen(sd, 1);
		int c = sizeof(struct sockaddr_in);
		cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
		if(cd < 0){
				printf("accept error, tell admin\n");
				return 0;
		}
		if( recv(cd, buf, 4, 0) != 4 ) return 0;
		if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;
		printf("Stage 5 clear!\n");

		// here's your flag
		system("/bin/cat flag");
		return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define STDIN 0
#define STDERR 2 

int main(){
	int pipes_si[2];
	int pipes_se[2];

	if((pipe(pipes_si)==-1)) { printf("error in pipes_si\n"); exit(1); }
	if((pipe(pipes_se)==-1)) { printf("error in pipes_se\n"); exit(1); }

	if(fork()){
		dup2(pipes_si[0], STDIN); close(pipes_si[0]); close(pipes_si[1]);
		dup2(pipes_se[0], STDERR); close(pipes_se[0]); close(pipes_se[1]);

		char *i_argv[101] = {[0 ... 99] = "A"};
		i_argv[65] = "\x00";
		i_argv[66] = "\x20\x0a\x0d";
		char *i_env[] = { "\xde\xad\xbe\xef=\xca\xfe\xba\xbe" };

		FILE* fp = fopen("\x0a", "a");
		if(!fp) printf("fp error\n");
		if( fwrite("\x00\x00\x00\x00", 4, 1, fp)!=1) printf("fwrite error\n");
		fclose(fp);

		execve("/home/input/input", i_argv, i_env);
	}
	else{
		write(pipes_si[1], "\x00\x0a\x00\xff", 4);
		write(pipes_se[1], "\x00\x0a\x02\xff", 4);

		sleep(2);
		int client;
		struct sockaddr_in c_addr;
		client = socket(AF_INET, SOCK_STREAM, 0);
		if(client == -1){
			printf("socket error, tell admin\n");
			return 0;
		}
		c_addr.sin_family = AF_INET;
		c_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
		c_addr.sin_port = htons( 25005 );

		if( -1 == connect(client, (struct sockaddr*)&c_addr, sizeof(c_addr)))
		{
			printf("connection fail\n");
			exit(1);
		}
		write(client, "\xde\xad\xbe\xef", 4);
		sleep(3);
		close(client);
	}
}



Introduction:

  본 문제는 input이라는 프로그램과 커뮤니케이션 하며, 프로그램에서 요구하는 정보를 전달해 주는 문제. input이 요구하는 정답을 하나씩 넣어주면 스테이지가 하나씩 클리어 되고, 모든 스테이지가 클리어 되면 마지막에 flag를 출력함


How to solve:

  사실 어떻게 푼다는 것을 설명하는 것은 조금 어려울 것 같고, 그냥 프로그램이 요구하는 결과들을 하나씩 넣어주면 풀리게 된다. 시스템의 /tmp에 개인용 폴더를 만들고, 여기에서 익스플로잇을 작성해 돌렸다.

  문제를 풀며 한 가지 고민을 하게 만들었던 것이 있는데, 2번 째 스크립트의 20번 줄에 배열을  100칸만 선언하면 이상하게 부모프로세스에서 자식프로세스에서 실행된 input이라는 프로그램에 값을 넣어줘도 아무런 출력을 하지 않았다는 것이다. 이에 대한 것은 사실 아직도 잘 모르겠다.. (쨋든 101칸 이상을 선언하면 정상적으로 출력이 된다..) 

  이렇게 해서 stage 5 clear까지 화면에 출력되게 한 후 flag의 내용을 봐야하는데, 이를 위해 flag를 익스플로잇을 작성했던 개인용 폴더로 옮겨와야 한다. 하지만 권한 문제로 flag파일 본체를 개인 폴더로 옮겨올 수는 없으므로, 그림 1과 같이 심볼릭 링크를 이용하였다.


<그림 1> 익스플로잇을 작성하던 폴더에 flag파일의 심볼릭 링크를 만듬


<그림 2> 문제 해결


References:

1) 여러 시스템 함수들 - http://forum.falinux.com/zbxe/index.php?_filter=search&mid=C_LIB&search_target=title&search_keyword=recv&document_srl=441107

2) 어떤 분이 올려주신 답안 - http://rk700.github.io/writeup/2014/11/16/input/

'Pwnable.kr' 카테고리의 다른 글

[3pt]collision  (0) 2015.08.07
[1pt]mistake  (0) 2015.08.06
[1pt]cmd1  (0) 2015.08.06
[1pt]fd  (0) 2015.08.06
[5pt]bof  (0) 2015.08.06
Posted by Hugh_K
l