동적, 정적 라이브러리 차이점에 대해서 알아 보기로 하자.

정적 라이브러리는 프로그램과 같이 컴파일 & 링크 되어 실제 오브젝트 파일 내에 포함 되어서 실행 되는 라이브러리이다. 라이브러리와 프로그램이 합체(?) 되기 때문에 정적 라이브러리와 링크 하면 프로그램 용량이 늘어나는 현상을 볼 수 있다.

프로그램과 합체가 되면 단점도 생기는데 라이브러리가 업데이트 되었을 때 그 라이브러리를 사용한 프로그램의 업데이트 버전을 어떻게 배포 하느냐 이거다-_-.. 업데이트가 쉽지 않다.(반면에 속도는 빠르겠지) 이래서 DLL이라고 불리우는 동적 라이브러리가 탄생하게 되었는데 프로그램에 합체 된 정적 라이브러리를 밖으로 꺼내 놓기 시작했다. 이게 바로 동적 라이브러리이다. 이러면 아주 편하게 수정 & 배포를 할 수 있으리라 생각 했겠지만 다른 문제점이 있으니.. 속도가 느려지는 단점이 있다. 동적 로더에게 질의를 날려서 라이브러리 찾고 메모리에 올리고 콜하고블라블라 아무튼 복잡해 진다.(이 과정은 다음에 포스팅)

그럼 어떻게 동작하는지 메모좀 해볼까..

아래 프로그램으로 동적 라이브러리를 들여다 보자. 어래 동적 라이브러리가 어딧어? 하시는 분들도 있겠지만 printf는 glibc에 포함된 동적 라이브러리라는 사실. 파일 분석의 흥미진진함을 더해주기 위해 전역변수도 몇개 추가 했다.

사용자 삽입 이미지

main.c 소스!

main 프로그램을 생성 후 nm 명령어를 사용해서 어떤 심볼들이 사용 되었는지 한번 보자.

사용자 삽입 이미지

숫자     알파벳     심볼명

으로 이루어진 것을 볼 수 있다.
앞의 16진수는 대략 가상 주소 겠고.. 알파벳은 찾아봐야겠고;; 마지막은 심볼명을 의미한다.

T : Text 영역(code)
U : 정의 안된 심볼
B : 초기화 안된 데이터(BSS)
D : 초기화 된 데이터
R : Read only data

자 여기서 중요한건 U로 표시된 undefined 심볼이다. 즉 좌측 캡춰 화면에 printf@@GLIBC_2.0 으로 되어있는.. 뭔지 모르겠지만 가상 주소도 안붙어 있네-_-; 이거이 동적 라이브러리와 관련좀 있는 것으로 추정된다.


그외에 전역 변수로 지정한 gVal~~~ 변수들은 B로 되어있는 것을 볼 수 있다. 여기서 아~ gValInit은 0으로 초기화 되어있는데 왜 초기화 안된 데이터 영역에 있나? 하실 수도 있겠지만 0으로 초기화 된 것들도 BSS 영역으로 갑니다. 만약 gValInit 변수에 100을 넣었으면 D라고 표시 됩니다.

readelf 명령어를 사용해 더 자세히 들여다 보자.
사용자 삽입 이미지

readelf -a main

음.. Entry point address는 0x8048310 이군.. gdb로 분석할 때 이곳에서 부터 시작하면 되겠다. 중요한건 이 부분이 아니고 Dynamic section 쪽에 보면 이 프로그램을 실행 시키기 위해 필요한 동적 라이브러리 목록을 볼 수 있다. NEEDEED가 보일때까지 스크롤 해보자. 슉슉

0x00000001 (NEEDED)                     Shared library: [libc.so.6]

자 이 부분 중요하다. 정적 라이브러리와 다르게 동적 라이브러리는 실행 프로그램에 포함 되는 것이 아니라고 했다. 그러면 정적 라이브러리 같이 합체(?) 되는 것도 아닌데 어떻게 이 프로그램이 동적 라이브러리와 연관이 지어지느냐 답은 요기 있다. 컴파일러가 이 프로그램은 이런이런 라이브러리를 사용 합니다. 라고 NEEDED 로 실행 파일에 적어 놓는다. 로더가 아~~ 얘는 이런 라이브러리를 사용하는군.. 이라고 생각하게 되고 이 정보를 어떻게 든 참고해서 프로그램 런타임시에 사용 될 것이라고 생각 된다.


.. 다 적을려고 했는데 너무 피곤하다. 너무 바쁘고 ㅠㅠ To be continue 해야겠다... 다음엔 gdb로 런타임상에서 동적 라이브러리가 어떻게 동작하는지 알아보겠따~~ GOT, PLT 기대하시라

Creative Commons License
Creative Commons License
2009/11/20 00:49 2009/11/20 00:49

[로그인][오픈아이디란?]

아오~ 보안 프로그램 만든다고 피터지게 분석할  때가 어제 같은데 다시 보니까 기억도 안나네 낄낄


ABI(Applcation Binary Interface)
애플리케이션이 지켜야 할 바이너리 레벨의 규약. 함수 호출 시 스택 또는 레지스터 사용법, 심볼 name mangling 규칙등이 정해져 있다. OS, 프로세서 별로 정의 되어짐

BSS(Block Started by Symbol Segment)
초기화 되지 않은 데이터가 위치하는 세그멘트. C의 전역 변수로 int global; 과 같은 초기값이 지정되지 않은 데이터가 들어간다. 오브젝트 파일 내에서는 크기를 갖지 않고 프로그램 시작시 커널에 의해 0으로 초기화. ELF 에서는 .bss

DSO(Dynamic Shared Object)
GNU/리눅스에서는 동적 링크하는 공유 라이브러리를  DSO 라고 한다.

DWARF(Debug With Arbitrary Record Format)
디버그 정보를 저장하기 위한 데이터 형식.

PIE(Position Independent Exeutable)
위치 독립인 실행 파일. 최신의 GNU/리눅스에서 작성할 수 있다. 보안 향상의 장점이 있음

PIC(Position Independent Code)
임의의 주소에 로드 가능한 코드. 데이터 액세스나 점프는 상대 주소로 수행한다. 위치 독립 코드

GOT(Global Offset Table)
PIC 를 실현하기 위해 필요한 데이터 PIC 에서는 전역 데이터로의 접근을 GOT를 이용해 간접적으로 참조한다.

PLT(Procedure Linkage Table)
동적 링크를 실현하기 위해 필요한 데이터. GOT 와 함께 사용해서 동적 링크한 공유 라이브러리 함수를 간접적으로 호출할 수 있다.

POSIX(Portable Operating System Interface for Unix)
시스템콜, 시그널과 같은 OS의 API를 규정하는 규약. 대부분의 유닉스 계열 OS 는 POSIX를 기반으로 하고 있다.

TLS(Thread Local Storage)
여러 스레드에서 동일한 이름의 변수를 사용하더라도 실제로 각 스레드의 독립된 영역에 저장 되는데 이를 TLS 라고 한다. GCC 에서는 __thread 라는 키워드를 사용해서 TLS 를 다룬다.

재배치(Relocation)
기계어 코드에 포함된 주소를 링크 시에 또는 로드 시에 수정하는 것

시그니처(Signature)
이름, 인수, 반환 값의 형태에 따라 결정 되는 함수의 형식. 보통 C나 C++ 등의 컴파일 언어에서 이름이 같아도 시그니처가 다른 함수를 호출하려하면 경고 또는 에러가 발생한다.

Stack frame
인수나 지역변수, 보존된 레지스터, 반환 값 주소 등 함수 호출에 필요한 정보를 정리한 것. 간단히 프레임이라고도 함

Toolchain
컴파일러, 링커, 어셈블러 등 네이티브 프로그램을 생성하기 위해 필요한 일련의 툴을 총칭

Demangle
name mangling 된 심볼을 원래의 읽기 쉬운 심볼로 복원 시키는 것 예) _ZN3Foo3BarE -> Foo::Bar


참고자료
BINARY HACKERS 한빛

Creative Commons License
Creative Commons License
2009/06/03 15:22 2009/06/03 15:22

[로그인][오픈아이디란?]