본문 바로가기

Research/Etc

입출력 리다이렉션





Popen 을 이용한 리다이렉션을 하고싶은데.

하나의 스크립트로만 사용을 하고싶은데! 잘 안된다.

그냥 단순히 subprocess.Popen( '....', stdin = subprocess.PIPE, stdout=subprocess.PIPE)

이렇게 주고 어떻게든 짜면 될 것 같아서 별짓 다 했지만... buffered 라는게 있다고 하네.

그래서 혹여나 퍼너블 시에 canary를 구하는 등의, 상호 동기적인(synchronous한) 데이터의 주고받기가 필요한 경우에는... 다른 방법을 써야 겠고.

그게 아니면. 그냥 일방적으로 데이터를 밀어넣기만 하면 되는 경우는

아래와 같이 해도 되겠더라.


int main()

{

어쩌고저쩌고 초기화

for(i=0; i<2; i++)

{

scanf("%s", buf);

printf("string : %s\n", buf);

memset(buf, 0x00, sizeof(buf));

}


return 0;

}


뭐 이런식으로 2 번의 루프가 생길 때에는

아래처럼


import sys

import subprocess


proc = subprocess.Popen("./cheese", stdin = subprocess.PIPE, stdout = subprocess.PIPE)


proc.stdin.write('333\n')

sys.stdin.flush()


proc.stdin.write('blahblahblah\n')

sys.stdin.flush()


print proc.stdout.readline()

sys.stdout.flush()


print proc.stdout.leadline()

sys.stdout.flush()



개행문자 \n 과, sys 라이브러리의 flush 를 잊어버리지 말 것

처음에 그냥 다 밀어넣고, readline 으로 쭉쭉 받아야 한다.


젠장.

2 점 대에서 하려니 이래저래 막막하다.

그냥 퍼너블킷을 사용해야 하나 ㅠ




------------------------------------------------------


C로 한 리다이렉션.


아래의 샘플 코드


sample1.c

int main()

{

char buf[0x100] = {0,};

printf("this is child!\n");

scanf("%s",buf);

printf("out : %s\n",buf);


return 0;

}


sample2.c

int main()

{

char buf[0x100] = {0,};

write(1, "this is child!\n", 15);

read(0, buf, 0x100);

write(1, buf, 0x100);


return 0;

}



샘플 2에서는 잘 되는데, printf / scanf 를 사용하는 샘플 1에서는 리다이렉션이 잘 안됨.

조언을 구해보니, C Library 에서의 성능 최적화 때문에, printf 를 몰아서 한다. 그래서 버퍼링이 생긴다. 는 답변이 돌아왔고... 실제로 strace 를 찍어보면 입력부터 받더라.

좀 신기한 것은, 샘플코드만 돌렸을때는 그냥 생각했던 순서대로 read-write 인데... parent에 물려서 돌리면. write 부터 받고 출력을 한꺼번에 몰아서 한다는 거;


그래서 하여튼 샘플코드 완성이다. child 프로세스가 어떻게 버퍼링을 하는지 확인하고 그때그떄 처리해야지.

아래는 fork 코드



#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>


int main(int argc, char* argv[])

{

int readfd[2];

// readfd[0] : Parent read from child to

// write[1] : Parent write to child

int writefd[2];

// readfd[1] : for write from child to parent

// wirte[0] : for read from parent to child


pipe(readfd);

pipe(writefd);


pid_t pid;

pid = fork();


if(0 == pid) // child

{

printf("%d %d\n", readfd[0], writefd[1]);

dup2(readfd[1],  1); // stdout on child go to readfd

dup2(writefd[0], 0); // stdout on child


execl(argv[1],NULL);

exit(0);

}

else

{

close(readfd[1]); // we only used read descriptor in readfd

close(writefd[0]);// we only used write descriptor in writefd

}


write(writefd[1], "hi\n", 4);

fflush(stdout);


char msg[0x100];

memset(msg, 0x00, 0x100);

read(readfd[0], msg, 0x100);


write(1, msg, 0x100);

//printf("out : %s\n", msg);


return 0;

}


잘 사용해야지.

림지님, 알렉스 형님 감사드립니다.







'Research > Etc' 카테고리의 다른 글

Hex-rays Decompilation failure  (0) 2018.02.12
ws filter  (0) 2016.09.06
[github] syncing a fork - fork 한 리파지토리 업데이트 하기  (0) 2015.07.16
설치된 드라이버 살펴보기  (0) 2013.12.10