농소

프로세스 메모리 구조, 스택 레지스터, 함수 본문

Security/System Hacking

프로세스 메모리 구조, 스택 레지스터, 함수

농소 2018. 1. 23. 03:09

프로세스 메모리 구조



우선 메모리 구조를 확인하기 위해서 sleep이라는 함수를 이용해서

 현재 동작중인 프로세스 메모리구조를 확인해 보겠다.



< ps -ef 로 현재 동작중인 프로세스를 확인 >


현재 sleep을 이용한 a.out실행파일이 동작중임을 알 수 있고 pid가 802인것을 확인 할 수 있다.



< 리눅스 메모리 구조 >


메모리 구조를 확인하기 위해서 proc 임시 디렉토리 -> pid 디렉토리 -> maps를 보면 확인할 수 있다.


< 현재 a.out실행파일의 메모리 구조 >



자세히 살펴보도록 하자.


메모리 구조를 보았을때 0x00000000 - 0x08047999 범위까지는 사용을 하지않고

 0x08048000부터 사용을 하는것을 알 수 있다


08048000-08049000 r-xp 00000000 03:01 425345     /root/a.out

이는 사이즈를 봤을때 4096 byte = 4k인 것을 확인 할 수 있고

권한이 rx인것을 봐선 text segment인것을 알 수있다.


08049000-0804a000 rw-p 00000000 03:01 425345     /root/a.out

4k 만큼 메모리에 적재, rw 이므로 data, bss, heap 인 것을 확인가능


0804a000-40000000

heap을 위한 예약된 메모리 공간(saved memory)


0x08048000 - 0x3fffffff 까지

data, bss, heap세그먼트가 사용하는 영역 나머지는 heap이 확장 될때 사용할 수 있는 예약된 메모리 영역이다.


40000000-40013000 r-xp 00000000 03:01 310116     /lib/ld-2.1.3.so

40013000-40014000 rw-p 00012000 03:01 310116     /lib/ld-2.1.3.so

40014000-40016000 rw-p 00000000 00:00 0

4001c000-40109000 r-xp 00000000 03:01 310123     /lib/libc-2.1.3.so

40109000-4010d000 rw-p 000ec000 03:01 310123     /lib/libc-2.1.3.so

4010d000-40111000 rw-p 00000000 00:00 0

공유된 라이브러리 파일 ( shared memory )



bfffe000-c0000000 rwxp fffff000 00:00 0

stack 메모리 영역


0xc0000000-0xffffffff 

커널영역 - 접근 불가능


스택의 시작은 c0000000 부터 시작되고,

 스택은 공유 라이브러리, 프로세스, 함수 등이 스택메모리를 사용한다.

stack의 할당은 높은곳에서 낮은곳으로 할당이 되고 메모리같은 경우 낮은곳에서 높은곳으로 할당이 된다.

즉 스택은 쓰면 쓸수록 주소가 줄고 메모리는 쓸수록 주소가 높아진다.



스택 레지스터





ESP : STACK POINTER ( 스택의 현재 위치를 알 수있는 레지스터( =TOP의 위치 ) )

EBP : BASE POINTER ( 한번 사용하면 값이 변경되지 않는 레지스터 ( 기준점 ) ) 





EIP 레지스터 ( Extended Instruction Pointer ) 

  - 다음에 실행해야할 메모리의 주소를 저장하고 있는 레지스터

    현재 명령어를 사용한 후 EIP 레지스터에 저장되어있는 주소에 위치한 명령어를 실행.



< 수정 ) push eip가 jmp앞에 존재해야하고, sum 레이블에 jmp 가 아니라 pop eip를 사용. >




이제 eip를 이용하여 jmp와 레이블을 추가적으로 사용하지 않고서도 작성할 수 있다.



함수


- asm에서는 함수라는 개념이 없음

- 허나 기계어로 직관적으로 표현이 되어있으므로 함수처럼 표현할 수 있다.



자 이제 스택을 이용해 인자를 전달하고 회수하는 asm을 함수처럼 구현해본다


c언어

int sum( int a, int b)<-- 지역변수

{

  return a + b;

}


int main()

{

  int result = 0;


  result = sum( 10, 20 );

  pirntf("sum: %d\n, result);


  return 0;

}


처음 시작하기 전 상태 saved eip <- esp

call main을 통해서 main 엔트리포인트 시작



asm언어





[실습]


정수 5개를 입력하고 합을 구하는 함수를 만들어라. < 배열은 지역변수 x >




extern printf

extern scanf


segment .data

input   db      '%d', 00

output  db      '%d', 10, 00


segment .bss

buffer  resd    5


segment .text

global  main


func1:

        push    ebp

        mov     ebp,    esp


.loop:

        mov     eax,    dword [ebp+8]

        cmp     eax,    5

        je      func1_end


        mov     edx,    buffer

        mov     ecx,    dword [ebp+8]

        imul    ecx,    4

        add     edx,    ecx


        push    edx

        push    input

        call    scanf


        inc     dword [ebp+8]

        jmp     .loop


func1_end:

        mov     esp,    ebp // 쓰는 이유. 함수에서 사용했던 stack메모리를 초기화

        pop     ebp

        ret


func2:

        push    ebp

        mov     ebp,    esp


.loop:

        mov     eax,    dword [ebp+8]

        cmp     eax,    5

        je      func2_end


        mov     ecx,    dword [ebp+8]

        imul    ecx,    4


        mov     edx,    0

        mov     edx,    dword [buffer + ecx]

        add     dword [ebp+12], edx


        inc     dword [ebp+8]

        jmp     .loop


func2_end:

        mov     esp,    ebp

        pop     ebp

        ret


main:

        push    ebp

        mov     ebp,    esp

        sub     esp,    8


        mov     dword [ebp-4],  0 ; result

        mov     dword [ebp-8],  0 ; len


        call func1


        mov     dword [ebp-8],    0


        call func2


        push    dword [ebp-4]

        push    output

        call    printf