포너블 문제를 풀다보면 바이너리 자체에서 소켓을 생성한 다음 I/O를 하는 문제가 있다.
근데 이러한 문제들은 일반적인 방법으로 쉘을 얻게되면 interactive()가 잘 되지 않는다.
왜나면 system이 /bin/sh의 입력과 출력을 부모 프로세스의 파일디스크립터 0과 1에 각각 연결하기 때문.
그래서 정작 쉘이 열리지 않게 되므로 작성한 쉘과 상호 작용하려면, 파일디스크립터 0과 1을, 통신 하고 있는 소켓의 파일디스크립터로 바꿔야 한다.
이렇게하려면, 먼저 stdin과 stdout에 대한 파일 디스크립터를 닫기 위해 close (0)와 close (1)을 호출해야한다. 그리고 dup (socket fd)를 두 번 호출하여 소켓을 사용하는 파일 디스크립터 0과 1을 생성 할 수있다. (ROP를 이용해 실행)
사용하고 있는 소켓의 파일 디스크립터를 찾는 방법은 아래와 같다.
gdb로 해당 바이너리의 socket이 생성된 시점에 BP를 걸고 아래와 같이 하면 된다.
$info proc 명령어로 해당 프로세스 넘버를 확인한 후
$shell ls -la /proc/[프로세스ID]/fd 로 소켓의 파일디스크립터를 확인하고 exploit을 작성할 때는 이 파일디스크립터를 작성해주면 된다.
rop 과정
close(0) - close(1) - dup(socket fd) - system("/bin/sh")
이런식으로 rop를 하면 된다. (CTF에서는 바이너리 안에 close()를 자체적으로 해놓은 문제도 있다.)
ref.http://research.hackerschool.org/Datas/Research_Lecture/remote2.txt