pwnable.kr의 Toddler's Bottle 문제 중 input 문제를 풀려고 하였었다.

 

제공된 input.c의 소스 코드 중,

 

if (strcmp(argv['A'], "\x00")) return 0;

 

라는 부분이 있었는데, 이를 python process 생성 API를 이용하여 인자를 넘겨주려고 했다.

 

os.system, subprocess.Popen, subprocess.run 등의 API를 이용할 수 있었는데, \x00 의 NULL 바이트를 인자로 넘겨주자 항상 에러가 났다.

 

그래서 다른사람이 작성한 write up을 확인해보니 pwntools의 process API를 이용하여 풀이를 하였는데, 거기서는 NULL 바이트를 인자로 주어도 아무런 상관이 없었다.

 

그래서 궁금증이 발동한 나는 pwntools의 process API를 한번 확인해 보았다.

 

process.py 코드 링크는 다음과 같다.

 

https://github.com/Gallopsled/pwntools/blob/dev/pwnlib/tubes/process.py

https://raw.githubusercontent.com/Gallopsled/pwntools/dev/pwnlib/tubes/process.py

 

process class를 정의해서 사용하고 있는데, 생성자인 __init__ 부분을 확인해보니, subprocess.Popen()을 이용해서 프로세스를 생성하는 것을 확인할 수 있었다.

 

그런데 어떤 차이가 있길래 NULL Byte Argument를 넘겨주어도 잘 실행이 되는가 싶어서, Popen 실행하기 직전의 Argument 리스트를 찍어보니, "\x00"인 NULL Character included string을 ""인 Empty String으로 치환되어 Popen API 인자로 넘어가는 것을 확인할 수 있었다.

 

확인해보니 _validate 함수에서 해당 처리를 하는데, 각각인자의 rstrip("\x00")를 하는 과정에서 사라진 것이다.

 

뭐 다시 생각을 해 보면, C로 작성한 바이너리에서 main 함수의 argc, argv중 argv는 NULL terminated string들이고,

 

if (strcmp(argv['A'], "\x00")) return 0;

 

 

위 코드를 Pass하기에 단지 Empty string이기만 해도 strcmp 리턴값이 0이 될 것이긴 하다.

 

어쨋거나 이러한 삽질을 통해서 뭔가 잊고 있떤 사실을 하나 알게 되긴 하였다.

 

고로 subprocess.Popen과 같은 파이썬 API로 호출해서 pkr input 문제를 풀려면 'A' 번째 인자는 Empty string만 넣어도 된다는 것.

 

그리고 pwntools는 위대하다.

+ Recent posts