pwnable.kr input 문제를 풀어보자.
바로 접속해보자.
이번 문제도 flag와 실행파일 input, 소스 input.c가 있다.
input.c를 살펴보도록 하자.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #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; } | cs |
Stage 1에서 5까지 총 다섯 단계로 이루어져 있는 것을 볼 수 있다.
[Stage 1]
[Stage 2]
이전에 File Descriptor 개념을 fd 문제에서 알아본 적이 있었다.
fd가 0이면 stdin이므로 콘솔 입력으로 "\x00\x0a\x00\xff"를 입력받고, fd가 2이면 stderr로 "\x00\x0a\x02\xff"를 받아야 한다.
[Stage 3]
getenv() 함수는 name 이름을 가지는 환경변수에 저장된 값을 읽어온다. 환경변수는 "key=value" 형태로 저장되며, getenv()의 아규먼트로 들어가는 name 은 이 key 이름이 된다. 보통 환경변수는 프로그램의 환경설정을 위한 간단한 방법으로 널리 사용된다. 만약 일치하는 name 을 가지는 환경변수가 있다면 "값"을 되돌려주고 없다면 NULL 을 반환한다.(출처 : https://www.joinc.co.kr/w/man/3/getenv)
"\xde\xad\xbe\xef" key에 해당하는 value를 "\xca\xfe\xba\xbe"로 설정해주면 해결.
[Stage 4]
fread()의 구조는 다음과 같다.
1 | size_t fread(void *buffer, size_t size, size_t count, FILE *stream); | cs |
void *buffer |
파일 내용을 읽어들일 메모리 포인터 |
size_t size |
데이터 한 단위 당 크기 |
size_t count |
읽어들일 데이터의 개수 |
FILE *stream |
대상 파일 스트림 |
size * count만큼의 데이터를 대상 파일로부터 버퍼에 읽어들인다.
"\x0a"라는 파일에서 4바이트 만큼 읽어들인 값이 "\x00\x00\x00\x00"이면 해결.
[Stage 5]
이제 익스플로잇 코드를 제작해보자. pwntools라는 포너블 툴 킷을 이용한 python 코드를 작성했다. 원래 경로인 /home/input2/input에는 작성권한이 없다. 따라서 /tmp 디렉토리에 하위 디렉토리를 하나 만들고 아래의 코드를 작성했다.
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 32 | from pwn import * #stage1 argvs = [str(i) for i in range(100)] argvs[ord('A')]='\x00' argvs[ord('B')]="\x20\x0a\x0d" #stage2 stderr with open("./stderr", "w") as f: f.write("\x00\x0a\x02\xff") #stage3 environment = {"\xde\xad\xbe\xef" : "\xca\xfe\xba\xbe"} #stage4 with open("./\x0a", 'w') as f: f.write("\x00\x00\x00\x00") #stage5 argvs[ord('C')]='35555' target = process(excutable="/home/input2/input", argv=argvs, stderr=open("./stderr"), env=environment) #stage2 stdin target.sendline("\x00\x0a\x00\xff") #stage5 conn = remote('localhost', '35555') conn.send("\xde\xad\xbe\xef") target.interactive() | cs |
코드를 실행해보자.
어째서인지 모든 스테이지를 클리어 했음에도 플래그가 보이지 않는다. 이는 아래와 같이 flag를 보여주는 부분이 상대경로로 지정되어 있기 때문.
pwnable input 문제를 풀었다~
[참고문헌]
http://juns0208.tistory.com/40
http://forum.falinux.com/zbxe/index.php?document_srl=408226&category=520881&mid=C_LIB
http://popbox.tistory.com/66
https://www.joinc.co.kr/w/man/3/getenv
http://mintnlatte.tistory.com/28
http://forum.falinux.com/zbxe/index.php?mid=C_LIB&document_srl=430926
http://jhrun.tistory.com/228
https://mandu-mandu.tistory.com/76
http://gmltnscv.tistory.com/27
'WriteUp > pwnable.kr' 카테고리의 다른 글
pwnable passcode writeup (0) | 2019.01.01 |
---|---|
pwnable coin1 writeup (2) | 2018.12.30 |
pwnable.kr fd writeup (0) | 2018.12.29 |