PLT, GOT

Linux 2012. 5. 28. 23:30

정리

PLT는 Procedure Linkagble Table 이란 녀석인데,

프로그램이 호출하는 모든 함수들을 나열 하는 테이블이다.

GOT는 Global Offset Table 이라고 하며, 프로그램 실행 후, libc.so내의

실제 함수 주소가 저장되는 곳이다.


가장 처음 공유라이브러리 내의 함수가 호출 되었을 때, 동적 링커는 먼저 PLT를 본다.

PLT는 실제 호출될 함수를 나타내는 값을 _dl_rentime_resolve 함수의 인자로 넘기고

_dl_rentime_resolve 함수는 전달된 인자 값을 사용하여 호출된 함수의 실제 주소를 

구한 후, GOT에 저장 한 뒤 호출된 함수로 점프한다.

이후 동일 한 함수가 다시 호출하게 되면 동적 링커는

GOT에 저장되어있는 호출된 함수의 실제 주소로 바로 점프하게 되는 것이다.



출처 : http://lapislazull.tistory.com/54

블로그 이미지

kuku_dass

,

프로세스의 헤더 파일을 분석하여 GOT 테이블의 주소를 찾아 GOT 테이블에 있는

malloc/calloc/realloc/memset/free 등의 메모리 관련 함수와 애플리케이션의 힙

13

테이블에 접근하는 함수의 주소를 후킹된 함수의 주소로 바꾸어 주는 방법을

이용하였다.


출처 : 이화여자대학교 대학원

2010학년도

석사학위 청구논문

안드로이드 기반 시스템에서의 메모리 누수

탐지를 위한 테스트 방법과 사례 연구

컴 퓨 터 공 학 과

박 지 현

2011



Got 란

http://bbolmin.tistory.com/33

http://ezbeat.tistory.com/374

GOT의 주소값 구하고 값 바꾸기.

http://bbolmin.tistory.com/40

블로그 이미지

kuku_dass

,

Win CE 6.0 플랫폼에서 후킹하는 기법임. 리눅스에서는 다르게 해야함.



pcb 후킹 단계 - 메모리 폴트를 감지하는 후킹 함수 작성. malloc을 예로 작성.



1. 후킹 함수 준비.

스텝 1) 어떤 함수를 후킹 할지 결정하자. -우리는 malloc, free, memset 등

스텝 2) 목적을 위해 필요한 데이터들을 수집.(ex) profiling data for memory fault detection

2-1) memory fault detection 을 알기 위해 수집해야 하는 데이터들

* site : 메모리의 할당 및 해제가 발생하는 메모리 위치.

* Addr : 할당되거나 해제된 메모리 블락의 시작 주소.

* Size : 할당되거나 해제된 메모리의 사이즈.

* Usage: 메모리 용도? 사용량?

* Occurrence_count : 메모리 할당 요청 횟수에 따라 +1, 해제하는 횟수에따라 -1한다. 변수 하나를 가지고.

* Status : 각 메모리 주소마다 해당 주소에 최근에 할당, 해제, 접근 등 어떤 요청이 왔었는지가 기록되어있다.

  a주소에 Status가 (0,0,0,0) 이라면, a주소의 공간은 해제만 최근에 4번 일어났다는 의미. 


스텝 3) 후킹함수 작성

2. PCB의 위치 찾기.

스텝 1) Calculating the PCB base address

Step 2: Accessing the PCB memory space

3. PCB 후킹.(내가 원하는 주소로 특정 주소를 변경 - 함수테이블내에서)




정리 :

malloc을 후킹하고자 한다면.

먼저 hook_malloc 함수를 정의한다.(내가 하고자 하는 작업을 추가한 사용자 수정 malloc 함수)

해당 함수를 공유 메모리 공간에 올려야 한다.(모든 프로세스가 접근 가능 하도록)

그 다음 후킹 드라이버를 작성하여, 현재 프로세스의 pcb 내의

함수 테이블에서 malloc 함수의 시작 주소값을 내가 공유 메모리 공간에 추가해둔

hook_malloc 함수의 시작 주소 값으로 대체해준다. (후킹)


블로그 이미지

kuku_dass

,
커널 수정없이 application level 에서 시스템 콜을 후킹하기 위해서는 
LD_PRELOAD 라는 것을 이용하는 방법이 최선이다.!

http://kldp.org/node/87850


실제 후킹 예제는 답변에 있음.

블로그 이미지

kuku_dass

,

c 라이브러리 함수 중 하나인 malloc 함수를 후킹 할 수 있을까?

시스템콜만 후킹 가능한거 아니였어?!!!



리눅스 메모리 사용관련 디버깅 정보


  • glibc 의 hook 함수
    glibc 를 쓰고 있다면 malloc(), free() 의 사용을 hooking 할수가 있다.
    __malloc_hook, __free_hook 에다가 자신만의 hook 함수를 설치할수가 있다.

  • malloc() 의 사용 현황
    glibc 를 통한 malloc() 의 활동 현황을 보고 싶으면 mallinfo() 함수를 이용하면 된다.
    기타 glibc 의 memeory allocator 관련해서 많은 정보를 알고 싶으면 gnu glibc 홈피를 방문해라. 
    (http://www.gnu.org/s/libc/manual/html_node/Memory.html)
출처 : 도시의 엘프 http://cityelf.egloos.com/


이런..좋다 말았음. malloc_hook도 라이브러리 함수임.

블로그 이미지

kuku_dass

,

http://lxr.linux.no


완전 유명한 홈페이지인데.. 제대로 활용한지는 얼마 안된.. ;;

메인 페이지에서 원하는 커널 버전 범위에 해당하는 링크를 클릭 후~

상단의 drop box에서 원하는 커널 버전을 선택하면

리눅스 커널 전체 소스를 볼 수 있습니다.~ 완전 유용하다는거!! +_+


블로그 이미지

kuku_dass

,

읽기전용으로 sys_call_table이 수정되어서, 바로 수정한 후 insmod를 하게 되면

>> 죽었음


이라는 커널의 짧고 강렬한 멘트와 함께.. 모듈은 정상작동을 하지 못한다.

즉 sys_call_table[index] = our_func  이런식으로 수정하기 전에 아래와 같은 함수를 호출해주어야 한다.

static void disable_page_protection(void)

{

unsigned long value;

asm volatile("mov %%cr0, %0" : "=r" (value));

if ( value & 0x00010000) {

value &= ~0x00010000;

asm volatile("mov %0, %%cr0": : "r" (value));

}

}


static void enable_page_protection(void)

{

unsigned long value;

asm volatile("mov %%cr0, %0" : "=r" (value));

if (!(value & 0x00010000)) {

value |= 0x00010000;

asm volatile("mov %0, %%cr0": : "r" (value));

}

}


사용예)


disable_page_protection();

sys_call_table[__NR_open] = our_open;

enable_page_protection();


참고 : http://blog.naver.com/kkn2988?Redirect=Log&logNo=138441227

블로그 이미지

kuku_dass

,

        for( ptr = (unsigned long)_read_lock;

                ptr < (unsigned long)&init_mm ; ptr += sizeof(void *))

        {

                p = (unsigned long *)ptr;

                if ( p[6] == (unsigned long) sys_close)

                {

                        return (void**)p;

                }

        }

기존 sys_call_table 의 위치를 찾기위해 공개심볼을 이용하는 방법중

2.6.32-41 generic 에서 "init_mm" [~~~~~} undefined 라는 경고에 봉착했고..

insmod로 모듈을 로드가 제대로 되지 않았다.. ㅠ

위의 init_mm 대신 init_task.active_mm 을 이용해보자.

        for( ptr = (unsigned long)_read_lock;

                ptr < (unsigned long)&init_task.active_mm ; ptr += sizeof(void *))

        {

                p = (unsigned long *)ptr;

                if ( p[6] == (unsigned long) sys_close)

                {

                        return (void**)p;

                }

        }

블로그 이미지

kuku_dass

,
블로그 이미지

kuku_dass

,