power-girl0-0

[pwnable] input 풀이 본문

War game/pwnable.kr

[pwnable] input 풀이

power-girl0-0 2022. 2. 7. 23:05
728x90

해당 문제는 디컴파일하지 않고, c언어 코드만 보고 풀 수 있는 문제이다.

본 글에서는 간단한 풀이 방법을 작성한다.


1. 공격 code 생성전, 알아가기!

(1) subprocess

새로운 프로세스를 생성하며, 이를 통해 입출력 파이프에 연결하고 반환 코드를 얻을 수 있는 모듈이다.

( 참고 : https://blog.naver.com/sagala_soske/221280201722 )

 

2. 문제 코드

문제의 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; //입력값이 100이 아니면 종료됨.
        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);  //buf에 저장할 4byte의 입력값을 받아옴.
        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 5단계까지 가면 flag를 확인할 수 있다.

 

3. Exploit Code

import socket
import subprocess
import os
import time

with open("\x0a", 'wb') as f:
        f.write(b'\x00'*4)

args = []
for i in range(100):
        args.append('A')
args[0] = './input'
args[65] = ''
args[66] = '\x20\x0a\x0d'
args[67] = '55000'

r, w = os.pipe()

spr = subprocess.Popen(args, stdin=r, stderr=r, env={b"\xde\xad\xbe\xef":b"\xca\xfe\xba\xbe"})
os.close(r)
time.sleep(1)

os.write(w, b'\x00\x0a\x00\xff')
os.write(w, b'\x00\x0a\x02\xff')
os.close(w)

time.sleep(1)
ip = '127.0.0.1'
port = 55000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip,port))
sock.send(b'\xde\xad\xbe\xef')
sock.close()

 

4. flag 획득


교훈 : 하나를 하더라도, 꼼꼼히 공부하자.

 

p.s. 오늘 '브레이킹 루틴'이라는 책을 읽었다. 기억에 남아, 기록해본다.

1. 원하는 인생은 늘 안전지대 밖에 있다.
2. 시도를 안해보는 것보다 실패하는 것이 낫다.
3. 남들 시선보다, 내가 하고자하는 꿈을 바라보고 안전지대를 벗어나 도전하자.

 

 

 

728x90

'War game > pwnable.kr' 카테고리의 다른 글

[pwnable] flag 풀이  (0) 2022.02.12
[pwnable] collision 풀이  (0) 2022.02.09
[pwnable] asm 풀이  (0) 2022.01.21
[pwnable] bof 풀이  (0) 2022.01.20
[pwnable] fd 풀이  (0) 2021.12.27
Comments