ssoL2 TISTORY

pwnable.kr [input] 본문

challenge/pwn

pwnable.kr [input]

ssoL2 2021. 6. 30. 16:15

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

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

 

 

 

 

 

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

 

 

 

 

 

 

 

 

단계가 엄청 많은데 다 통과하면 system 함수 실행 가능한 듯

이제 step을 정리해봅시다.

 

step1. argv

1. argc 인자 개수는 100개여야 하고

2. argv['A'] = argv[65] 즉, 65 + 1 = 66번째 인자는 \x00이여야 하고

3. argv['B] = argv[66] 67번째 인자는 \x20\x0a\x0d이어야 한다. 그러면 통과

=> 해야할 것

1. argv 100개

2. argv[65] = \x00

3. argv[66] = \x20\x0a\x0d

 

 

step2. stdio

read함수로 buf 배열 갖고 노는 상황.

1. read(0)이므로 표준 입력으로 buf가 \x00\x0a\x00\xff 이어야함

2. read(2)이므로 표준 오류로 buf가 \x00\x0a\x02\xff 이어야함

=> 해야할 것

1. 표준 입력은 pwntools로 send(\x00\x0a\x00\xff) 보냄

2. 표준 오류는 출력이니까 \x00\x0a\x02\xff를 담은 open file 만들어서 fd 가리키게 하면 됨

 

 

step3. env

env 환경 설정 해주면 됨.

=> 해야할 것

1. env 딕셔너리 만들어서 넘겨주면 됨

 

 

step4. file

파일 생성해서 해당 값 넣어주면 됨

=> 해야할 것

1. \x0a 이름의 open file해줘서 \x00\x00\x00\x00 넣어주면 되겠다.

 

 

step5. network

소켓 포트를 atoi(argv['C'])) 즉, argv[67]을 읽어서 숫자로 받아온다는 의미.

그 포트를 가지고 소켓 생성한 이후 쓱싹 해줘서 4byte 읽어와서 buf에 넣고 buf가 \xde\xad\xbe\xef어야 함

=> 해야할 것

1. argv[65] = 10101 넣어주고(내가 할 임의의 port번호)

2. remote(localhost, 10101) 연결하고 해당 소켓에 \xde\xad\xbe\xef 넘겨주면 됨

 

 

후 해야할 것들 끝내면 완료되겠다.

아 그리고

1. /tmp가서 mkdir로 폴더 생성 후 그 안에 ex.py 생성

2. system 함수에서 cat할 flag가 현재 주소에 없으므로 ln -s /home/input2/flag flag로 심볼릭 링크 

from pwn import *

#1
argvs = [str(i) for i in range(100)]
argvs[65] = '\x00'
argvs[66] = '\x20\x0a\x0d'

#2
#stdin is directly after
with open('./stderr', 'a') as f:
        f.write('\x00\x0a\x02\xff')

#3
envVal = {'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'}

#4
with open('./\x0a', 'a') as f:
        f.write('\x00\x00\x00\x00')

#5
argvs[67] = '10101'
#port open is after too


target = process(executable='/home/input2/input', argv=argvs, stderr=open('./stderr'), env=envVal)

target.sendline('\x00\x0a\x00\xff')
conn = remote('localhost', 10101)
conn.send('\xde\xad\xbe\xef')
target.interactive()

 

'challenge > pwn' 카테고리의 다른 글

pwnable.kr [leg]  (0) 2021.06.30
pwnable.kr [random]  (0) 2021.06.30
pwnable.kr [passcode]  (0) 2021.06.29
[FTZ] LEVEL 18 풀이  (0) 2021.02.23
[FTZ] LEVEL 17 풀이  (0) 2021.02.23
Comments