Pwnablekr_Toddlers Bottle_input

ssh로 접속하면 소스파일과 실행파일이 있다.

이번 문제는 여러가지 기초 지식에 대해 공부하도록 하는 문제이다.

C 파일의 핵심 알고리즘은 다음과 같다.

  • 메인함수 인자가 100개면 통과
  • 배열의 인덱스가 A의 아스키코드(0x41)인 곳의 값이 NULL 이면 통과
  • 배열의 인덱스가 B의 아스키코드(0x42)인 곳의 값이 \x20\x0a\x0d 이면 통과
  • strcmp는 서로 같을 때 0을 반환함에 주의한다.
  • stdin에서 읽은 값이 \x00\x0a\x00\xff 이면 통과
  • stderr에서 읽은 값이 \x00\x0a\x02\xff 이면 통과
  • \xde\xad\xbe\xef 이름을 가진 환경변수의 내용이 \xca\xfe\xba\xbc 이면 통과
  • \x0a 이름을 가진 파일의 내용이 \x00\x00\x00\x00이면 통과
  • 파일은 찾을 수 있는 위치에 있어야 함(등록된 경로나, 같은 폴더 등)
  • 메인 함수 인자의 인덱스가 C의 아스키 코드(0x43)인 곳의 값을 포트번호로 소켓 연결
  • 해당 포트로 \xde\xad\xbe\xef 를 보내면 통과

메인 함수에 문자열로 입력값을 주면 조건에서 요구하는 A번째 인자 내용 NULL에서 끊기게 된다. 그렇기 때문에 단순히 인자를 입력하는 방식으로는 100개의 인자를 줄 수 없다. 따라서 프로그램을 통해 실행시키는 방식을 이용하도록 한다.

위의 조건에 맞추어 인자를 설정하고, 파일을 만들고, 프로그램을 실행한다.

from time import *
from os import *
from socket import *
 
"""stage 1 : main function argument"""
 
arg = ['A']*100
arg[0x41] = ''
arg[0x42] = '\x20\x0a\x0d'
 
"""stage 2 : write some data in stdin"""
 
fd = open("in", O_RDWR|O_CREAT)
 
write(fd, "\x00\x0a\x00\xff")
write(fd, "\x00\x0a\x02\xff")
 
lseek(fd, 0, 0)
 
dup2(fd, 0)
dup2(fd, 2)
 
"""stage 3 : environment variable"""
 
env = {'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'}
 
"""stage 4 : file """
 
fd2 = open("\x0a", O_RDWR|O_CREAT)
write(fd2, "\x00\x00\x00\x00")
 
"""stage 5 : network """
 
port = 54321
arg[0x43] = str(port)
 
pid = fork()
 
if pid ==0 :
        execve('/home/input2/input', arg, env)
 
else:
    sleep(3)
 
    clientSock = socket(AF_INET, SOCK_STREAM)
    try:
        clientSock.connect(("127.0.0.1", port))
 
    except Exception as e:
        print "cannot connect"
 
    clientSock.send("\xde\xad\xbe\xef")
    wait()

단, 이 방법을 이용할 시 주의할 점이 있다. pwnable.kr에서 파일을 만들 수 있는 위치는 /tmp/내가 만든 디렉토리 이다. 위 조건을 통과하기 위해서는 파일을 만들어야 하고, 파일에 접근하기 위해서는 같은 디렉토리에서 프로그램을 실행해야 한다.

문제는 flag를 얻기 위해서는 system함수를 이용하여 /home/input2/flag 파일을 읽어야 하는데, 위치가 다르기 때문에 읽히지 않는다. 따라서 현재 디렉토리(/tmp/내가 만든 디렉토리)에 링크 파일을 만들어 주어야 한다.

ln -s /home/input2/flag /tmp/내가 만든 디렉토리/flag 명령어를 입력하여 flag라는 이름을 가진 링크 파일을 만들어 준다. 이렇게 하면 system 함수가 제대로 동작할 수 있다.

flag는 Mommy! I learned how to pass various input in Linux :) 이다.


tags: writeup, pwnable, elf file, linux, c lang, symbolic link