ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 정적라이브러리와 동적라이브러리로 컴파일하기
    표튜터와 함께하는 Pwnable/Pwnable 개념 및 정리 2019. 2. 17. 14:20

    정적라이브러리와 동적라이브러리를 각각 이용한 컴파일 방법이다.


    Statically link와 Dynamically link의 차이는 이전의 글에서 언급했으니 참고하기 바란다.

    https://xn--vj5b11biyw.kr/123




    정적라이브러리를 만드는 방법은 ar명령어를 이용하면 되는데

    ar 명령어를 이용하면 여러 프로그램에서 사용되는 함수를 포함한 오브젝트파일들을

    하나의 아카이브 파일( .a )로 모아놓을 수 있다.


    그렇다면 한번 ar 프로그램을 이용해서 라이브러리파일 (.a)를 만들어보겠다.

    우선 함수를 정의한 코드를 구현한다.


    < mylib.c >




    gcc를 이용해서 mylib.c의 오브젝트 코드를 생성한다.



    그 다음으로는 위에서 만든 라이브러리 함수를 호출할 프로그램을 만든다.


    < static.c >



    정적라이브러리를 포함시킨 옵션으로 컴파일을 진행한다.


    생성된 실행파일을 진행해보면 잘돌아가는 것을 확인할 수 있다.

    참고로 정적라이브러리와 statically linked는 약간 다른개념이라고 생각한다.

    statically linked가 조금 더 큰 범위라고 생각한다.

    그 이유는 Dynamic linked라도 자신이 정의한 특정함수를

    정적라이브러리로 컴파일하게되는 경우가 있기 때문이다.

    위의 경우가 바로 그러한 경우이다.

    Dynamically linked와 Statically linked는 공유라이브러리를 사용하는가의 차이가 큰 기준이라고

    생각하고 정적라이브러리의 사용은 말 그대로 함수가 정의된 

    라이브러리 파일을 바이너리에 포함시켜컴파일하는 것을 의미한다.


    정적라이브러리를 링크하게 되면 linker는 다른 오브젝트파일에서 정의되지않은 Symbol을 찾아

    지정된 정적라이브러리에서 해당 Symbol을 정의하고 있는 오브젝트 파일의 사본을 추출한 뒤

    실행파일내에 포함시키게된다. 그렇기 때문에 같은 라이브러리 함수를 여러 프로그램에서 사용할 시

    각가의 실행파일 마다 똑같은 라이브러리 함수의 코드가 포함되며 동일한 함수의 코드가 메모리 여러 곳에

    존재하게되므로 메모리나 하드디스크의 낭비가 일어난다.



    이번에는 공유라이브러리를 이용하여 컴파일을 해보도록 하겠다.

    공유라이브러리는 여러 오브젝트 파일을 하나의 오브젝트 파일로 만들어서 공유하는 방식을 이용한다.

    정적라이브러리처럼 함수코드가 실행파일 내부에 포함되는 것이 아니라 참조하는 방식으로 이용된다.


    공유라이브러리 생성방법이다.

    아까와같은 mylib.c 코드이다.



    < mylib.c >



    독립적인 코드로 만들기위해서 gcc에서 -fPIC 옵션을 사용하여 컴파일한 뒤,

     -shared 옵션을 이용해서 공유라이브러리를 생성한다.

    생성된 공유라이브러리파일은 등록을 해주어야 사용이 가능하다.


    아래의 경로의 파일에 가보면 include할 수 있는 문법(?)같은 것이 보인다.

    저 경로( /etc/ld.so.conf.d/ )에 .conf 파일을 생성하면 된다.



    /etc/ld.so.conf.d/라이브러리명.conf 로 파일 생성

    내부에 자신이 만든 공유라이브러리 파일( .so)의 전체경로를 등록해준다.



    ldconfig 명령어를 이용해서 캐쉬를 갱신해준다. 이렇게 하면 공유라이브러리를 다른 모든 실행파일에서 사용할 수 있게 된다.





    공유라이브러리를 링킹을 하여 컴파일했더니 실행파일이 생성되고 아주 잘 실행됨을 볼 수 있었다.


    ldd 명령어를 이용하면 해당 프로그램에서 요구하는 공유라이브러리들을 볼 수 있다.

    우리가 방금 만들고 등록해놓은 라이브러리파일을 참조하는 것을 확인할 수 있었다.



    공유 라이브러리를 링크한 실행 파일을 실행하게 되는 경우에는 

    동적 링커 로더(ld.so)가 해당 실행 파일에서 필요한 공유 라이브러리를 찾아내

    실행 시 해당 프로세스의 메모리 맵을 조작하여 공유라이브러리와 

    실행 바이너리가 같은 프로세스 공간을 사용하도록 해준다.



    그러므로 실행파일 내부에 라이브러리 코드가 포함되있지 않고 공유라이브러리에만 존재하기 때문에

    실행파일 배포시 함께 배포해야한다. 그렇지 않으면 라이브러리를 찾을 수 없다는 에러메세지와 함께 실행되지 않는다.



    참조 : https://bpsecblog.wordpress.com/2016/05/25/memory_protect_linux_3/


    * 독립적인 코드(PIC)로 만들기 위한 gcc 옵션 -fPIC *

    ex) gcc -c -fPIC mylib.c


    * 공유 라이브러리 .so파일 생성 *

    ex) gcc -shared -o libtest.so mylib.o


    * 공유 라이브러리 링킹 *

    ex) gcc test.c -o dynamic -ltest -L.

    ( -l 다음은 .so파일의 lib다음의 파일명 )


    < 주의 사항 >

    위의 설명처럼 컴파일을 하다가 조금의 삽질을 했고 그 결과는 다음과 같다.

    .so파일을 생성할 때 파일명을 되도록이면 lib로 시작하는 것이 좋다는 것이다. 


    그 이유는 동적 링커 로더(ld.so)가 해당 실행파일에 필요한 우리가 만든 공유라이브러리를 찾을 때

     /etc/ld.so.conf.d/에서 우리가 생성한 .conf파일에 등록된 경로에서 .so파일을 탐색하는데 

    이 때 lib로 시작하는 파일 이름으로 검색하는 것 같다.

     

    예를 들어 libtt.so파일이 있다고 가정하면 우리가 공유라이브러리 링킹 시

    gcc에서 컴파일시 -l 옵션을 주는데 이때 -ltt(.so의 파일명중 lib를 제외한 파일명) 이런식으로 옵션을 주게된다.

    하지만 .so파일이름을 tt.so처럼 만들어서 실험해보니 제대로 컴파일이 이루어지지 않았다.

    그러므로 동적 링크 로더는  /etc/ld.so.conf.d/.conf 경로에 있는 파일중

    lib로시작하는 libtt.so 파일을 찾게되는 것 같다.


    결론!!  .so파일명을 지을 때는 lib앞에 붙여주자!!



    반응형

    '표튜터와 함께하는 Pwnable > Pwnable 개념 및 정리' 카테고리의 다른 글

    /proc 디렉토리 관련 정리  (0) 2019.02.19
    PIC란  (0) 2019.02.17
    Mitigation의 종류  (0) 2019.02.15
    GDB 사용 시 set 명령어  (0) 2019.02.15
    PLT 와 GOT  (0) 2019.02.14

    댓글

Designed by Tistory.