ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • PIC란
    표튜터와 함께하는 Pwnable/Pwnable 개념 및 정리 2019. 2. 17. 17:47

    PIC (Postion Independet Code)란?


    메모리의 어느 공간에든 위치할 수 있고 수정없이 실행가능한 위치 독립코드를 의미한다.

    이 코드를 사용하는 각 프로세스들은 이 코드를 서로 다른 주소에서 실행할 수 있고 실행 시 재배치가 필요하지 않다.

    즉, 공유 라이브러리 내의 심볼들이 어느 위치에 있더라도 동작하게 해준다.


    보통 공유라이브러리를 만들때 -fPIC옵션을 이용해서 코드를 컴파일하며

    보통 GNU/리눅스의 공유라이브러리를 만들 때 각각의 .C파일을 PIC가 가능하도록 컴파일한다.


    예제를 통해 PIC가 있고 없고의 차이를 알아보겠다.




    아래와 같은 소스코드가 있다.

    < test.c >




    하나는 non_PIC로 하나는 PIC로 컴파일 했다.



    readelf의 -d 옵션으로 생성한 공유라이브러리들의 dynamic 섹션을 확인해 보니

    PIC가 아닌 공유라이브러리에는 text 내의 재배치가 필요하기 때문에 TEXTREL이라는 엔트리가 있고

    RELCOUNT(재배치 횟수)는 5로 PIC 공유라이브러리보다 컸다. 

    5인 이유는 printf함수를 2회 호출했음으로 PIC 공유 라이브러리에서보다 2회만큼 큰 것이다.


    PIC는 재배치가 필요없지만 공유라이브러리에서 RELCOUNT가 0이 아닌 이유는

    gcc가 기본적으로 사용하는 시작파일에 포함된 코드 때문이다.

    그렇기 때문에 nostartfiles 옵션을 컴파일 시에 넣으면

    RELCOUNT 값이 0 이되어 사라지게될 것이다.


    RELCOUNT 엔트리가 사라진 것을 확인했다.



    PIC가 아닌 공유 라이브러리는 예제 실행 시에 5개의 주소가 재배치되어야한다.

    현재 printf함수를 2번 호출하는 간단한 프로그램이기 때문에 재배치되는 숫자가 얼마없으나

    큰 프로그램의 경우 재배치수가 많기 때문에 프로그램 실행 시 재배치에 걸리는 시간도 커질 수 밖에 없다.

    또한 실행 시 재배치가 필요한 부분의 코드를 재작성하기 위해

    text 섹션 내의 재배치가 필요한 페이지를 로드하고 이를 재작성하는 과정을 거치다가

    copy on write가 발생하여 다른 프로세스와 text 섹션을 공유할 수 없는 상황이 발생할 수도 있다.

    이는 공유 라이브러리의 장점인 text 섹션을 다른 프로세스와 공유할 수 있는 것이 불가능해진다는 의미이다.


    * copy on write *

    한정된 Resource를 서로 다른 두개의 프로세서가 공유할 때 일어나는 것이다.

    프로세스들이 Resource를 공유할 때 공유하는 주체인 프로세스 중 하나가 공유중인 Resource에 대해

    수정을 요구할 시 발생한다. 왜냐하면 수정을 요구한 프로세스가 아닌 다른 프로세스에게 해당 Resource가

    중요한 역할을 하는 Resource일 수 있기 때문이다. 그러므로 Resource가 수정될 시 다른 프로세스에 영향을 끼칠 수 있다.

    이런 상황을 피하기 위해 적용되는 방법이 바로 copy on wirte이다. 평소에는 Resouce를 공유하다가

    수정할 경우가 생기면 Resource의 복사본을 사용하게 한다.  이후 각각의 프로세서의 포인터를 변경해주어

    이전과 같이 문제없이 동작하도록 하는 원리이다.

    참고 : https://talkingaboutme.tistory.com/451


    그렇기 때문에 공유라이브러리를 PIC로 사용하여 

    실행 시 재배치에 소요되는 시간을 줄이고 다른 프로세스와 코드를 공유한다는 장점을 이용하기위해 

    보통 공유라이브러리를 작성할 때 .C파일을 PIC로 컴파일하는 것이다.



    non PIC와 PIC의 또하나의 차이점을 설명하겠다.

    그건 바로 함수 호출 방식이다.



    다음과 같은 예시 코드가 있다.

    < func.c >


    < non PIC 공유 라이브러리의 경우 >

     non PIC의 경우 printf함수 호출 시  어떠한 주소를 호출하는데



    이 주소는 .text 섹션에 위치하는 주소이다.



    < PIC 공유 라이브러리의 경우 >

    하지만 PIC의 경우 함수 호출 시 plt를 경유해서 printf함수를 호출한다는 점이 차이점이다.







    반응형

    댓글

Designed by Tistory.