본문 바로가기

파이썬 공부

5.파이썬 REPL 기초 (pwnable fd 풀이 포함)

728x90
반응형
SMALL

read–eval–print loop (REPL), interactive toplevel, language shell

REPL이란?

Read = (코드를) 읽고

Eval = (읽은 코드를) 평가(실행) 하고

Print = (실행한 결과를) 출력하는

Loop = 루프 (반복)

 

read–eval–print loop (REPL), interactive top-level, language shell

대화식 프로그래밍 환경, 언어 쉘


파이썬 코드를 실행할 때 우리는 터미널을 켜고. python3 filename.py로 파일을 실행했지만.

이번에는 다르게 그냥 python3만 터미널에 써볼 것이다.

입력 후 모습

실행되는 대신에 무언가 입력할 수 있게 변했다.

이 창은 파이썬 코드를 "한줄 씩" 실행할 수 있게 도와주는 도구이다.

이 도구는 파이썬 코드를 간단히 테스트해보거나 숫자 계산을 할 때 유용하다.

코드 테스트 / 계산

보다시피 a = 10이라는 값을 지정해주고

print(a)라고 명령해주면 a 값을 출력해준다.

그리고 1+1 이라고 입력하고 엔터 하면

2라는 계산 값을 출력한다.

10*10이라고 입력하고 엔터 했더니 100이라는 값을 출력해줬다.

4/2라고 입력했더니 2라는 값을 출력해줬다.

4%3이라고 입력했더니 1이라는 값을 출력해줬다.


문자열이 잘 동작 하나 보고 싶을 때, 파일을 열어 코드를 한 줄 바꾸고 저장하고, 또 한줄 바꾸고 저장하며 결과를 확인할 수 도 있고

아니면 모든 코드를 적고 실행해 볼 수도 있겠지만.

한줄 한줄 입력해서 테스트 가능

이런 식으로 하나하나씩 직접 결과를 보며 테스트할 수 있다.

아니면 오늘 친구와 먹은 저녁 값을 n분의 1할 때 계산기로써 활용 가능하다.

오 8000원이구나

오~ 4만 원씩 5명이 먹었으므로 8000원을 지불하면 되겠구나! 고마워요 파이썬!(사실 폰 계산기 키는 게 더 빠르다)

이렇게 REPL 사용이 끝났으면 quit()를 써서 탈출해준다.

탈출 성공

quit()이라 해도 되고 exit()라고 해도 무방하다.

 


정리하자면..

>>> 100 + 100 #코드를 읽어서

processing #그 코드를 실행하고

200 #실행한 결과를 출력해주는

>>> # 이 과정을 반복해주는 도구

라고 REPL을 이해하도록 하자.

 

앞으로 REPL을 딱히 쓸 일이 많지는 않지만(?)

파이썬 코딩할 때 옆에 REPL을 띄워두고

잘 모르는 기능 및 코드를 테스트할 때 사용하거나 계산기로써 사용하면 아주 유용하다.


계산기로 활용하는 예는 포너블.kr의 toddler 섹션의 1번 문제 fd에서도 확인할 수 있는데.

http://pwnable.kr/play.php

 

http://pwnable.kr/play.php

 

pwnable.kr

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char buf[32];

int main(int argc, char* argv[], char* envp[])
{
	if(argc<2)
	{
		printf("pass argv[1] a number\n");
		return 0;
	}
	
	int fd = atoi( argv[1] ) - 0x1234;
	int len = 0;
	len = read(fd, buf, 32);
	
	if(!strcmp("LETMEWIN\n", buf))
	{
		printf("good job :)\n");
		system("/bin/cat flag");
		exit(0);
	}
	
	printf("learn about Linux file IO\n");
	
	return 0;
}

fd.c 소스.

if(argc<2)
{
	printf("pass argv[1] a number\n");
	return 0;
}

fd.c 코드 중 이 부분을 보면 

fd의 인자가 2개 미만이면 프로그램이 종료되는 것을 알 수 있다.

이를 피하기 위해서는 fd 파일의 인자를 최소 2개 이상 적어야 한다.

코드 내에서 int형 fd 변수에 첫 번째 인자를 int형으로 변형하여

atoi( argv[1] ) - 0x1234;

(atoi함수는 값을 입력할 때에 문자형을 인트형으로 변환시켜주는 값이다.)

변환된 값은 - 0x1234로 뺀다.

read(fd, buf, 32);

그리고 이 값이 read값의 인자로 들어간다는 것이다.

빼진 fd값이 read의 인자이다.

read 함수에서  int fd는 파일 디스크립터

buf는 파일에서 읽은 데이터를 저장할 메모리 공간.

len은 읽을 데이터의 크기.

 

파일 디스크립터란? 

fd에 0이 들어가면 표준 입력, read 함수의 fd에 0 값이 들어가면 buf에 표준 입력한 값을 넣을 수 있다.

fd에 1이 들어가고 read 함수가 실행된다면 buf안에 존재하는 값을 읽어 그에 대한 값을 출력해준다.

 

그러면 if문을 이용하여 buf안에 존재하는 값과 LETMEWIN\n이 동일하면 flag를 읽기가 가능해진다.

 

즉 strcmp함수로 LETMEWIN\n값과 버퍼에 있는 값을 비교해 같으면 flag를 출력해주는 것이다.


이때 REPL을 쓸 건데.

0x1234 = 4660

0x1234는 아스키 값이므로 10진수로 바꾸어준다. REPL을 이용하여 10진수로 바꿨더니 4660이란다.

그럼 이제 ./fd 4660을 입력하고 엔터 후 read가 표준 입력 스트림(stdin)을 열어주면 LETMEWIN이라 적고 엔터를 누르자.

마미!

플래그: mommy! I think I know what a file descriptor is!!

플래그 창에 복붙하자.

auth를 누르면 끝난다. 1포인트 획득!


이렇게 REPL사용법을 알아보았다.

포너블 fd 문제 풀이까지 같이 적었다.

fd문제를 푼 이유는! 파이썬 REPL을 활용할 수 있는 문제이기 때문이었다. (1번 문제라 쉽기도 하고.)

REPL을 잘 쓰는 프로그래머가 되자!

반응형
LIST