관리 메뉴

IT창고

System 메모리구조와 어셈블리어 함수 본문

보안/System

System 메모리구조와 어셈블리어 함수

방구석여포 2018. 1. 22. 22:00

메모리의 구조를 살펴보기 위하여 간단한 출력프로그램을 만들어보겠습니다.



출력을하고 sleep명령어를 사용한 프로그램입니다.

백드라운드로 전환하고 이 프로그램이 실행되는지 프로세스를 확인합니다.


실제로 방금 실행한 프로그램이 있는데 여기에 PID를 확인합니다. proc디렉토리는 가상디렉토리로 리눅스에서는 실행프로세스도 모두 실행파일의 형태로 존재를 합니다. 여기서 방금 실행한 프로그램의 PID는 851인데 /proc/851 디렉토리에 들어가면 파일들이 보입니다. 그중 maps파일은 프로세스에서 사용중인 메모리의 정보를 가지고 있습니다!

이 파일에서 메모리의 정보를 확인할수있으며 커널메모리의 정보도 포함합니다.


08048000-08049000 r-xp 00000000 03:01 980584     /testgsk/9/a.out

08049000-0804a000 rw-p 00000000 03:01 980584     /testgsk/9/a.out

여기는 세그먼트의 정보를 나타내며 실행권한을 확인할수있습니다. r-x인걸보면 text영역인것을 확인가능합니다.

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
여기는 공유라이브러리 영역을 확인할수있습니다. 4001부터 주소가 시작되는걸 볼수있습니다. 여기도 elf 실행파일의 구조를 따릅니다.

bfffe000-c0000000 rwxp fffff000 00:00 0
bf..로 시작하며 ff..로 끝나는 이 부분이 바로 스택메모리 부분입니다.

메모리는 할당할때마다 높은 주소로 할당을 하는데 스택메모리는 커널메모리의 침범우려가 있어서 높은주소에서 낮은 메모리로 할당합니다.
|  Heap  |    shared lib   |   stack   |  이러한 메모리구조를 가집니다.
메모리구조는 리눅스의 버전이 높아질수록 메모리의 구조가 달라집니다!

어셈블리어로 넘어가서 어셈블리어는 push명령어로 스택메모리를 할당합니다. 기본적으로 스택은 4byte씩 push됩니다.

스택메모리에서 데이터를 꺼내올때 사용하는 명령어로 pop이 있습니다. pop으로 꺼내올수있는건 스택에서 가장 나중에 들어간것만 꺼내올수있으며 임의로 꺼내올수는 없습니다. 이러한 스택메모리의 구조를 LIFO구조라고 합니다.

이러한 스택메모리를 다루는 esp, ebp 레지스터가 있습니다.
esp 레지스터의 역활은 현재 TOP(가장 나중에 들어간 주소)의 주소를 가지고 있습니다. 그렇기에 esp레지스터의 값은 항상 변동됩니다.
ebp 레지스터는 베이스포인터 레지스터로 값의 변동이 거의 없습니다. 스택메모리에서 기준점으로 사용이 됩니다.

현재 스택메모리의 값을 직접 확인해보겠습니다.


esp의 주소값은 정확히 8byte만큼 차이가 나는걸 눈으로 확인할수있습니다.

어셈블리어의 함수에 대해 알아보겠습니다.
먼저 전역변수를 사용한 간단한 프로그램을 만들어보겠습니다.
C언어로 확인하면 아래와 같습니다.
int result =0;
int a, int b

int sum()
{
return a+b;
}

int main()
{
result = sum(10,20);
printf("sum: %d\n", result);

retern 0;
}

어셈블리어로 바꿔보도록 하겠습니다.

이렇게되면 함수의 기능을 구현할수있습니다. 그렇다면 C언어 컴파일러는 어떻게 컴파일이될지 알아보겠습니다.

스택메모리에는 eip 레지스터가 있습니다 eip레지스터는 다음에 들어갈 메모리의 정보를 가지고있는데 eip의 값은 미리 스택메모리 어딘가에 저장해둡니다.



지금 사용하는 어셈블리어는 NASM문법으로 만들었습니다. NASM에서는 eip 레지스터를 직접 사용할수없습니다 대신 ret명령어가 대신합니다.


이번에는 전역변수를 지역변수로 만들겠습니다.


esp레지스터를 옮겨주면 메모리를 사용할수있습니다. esp는 pop을 하기 전까지는 사라지지않습니다. ebp레지스터를 기준으로 합니다. leava명령어로 꼭 메모리를 회수해주어야합니다. 

메모리회수에 대해서는 콜러(caller)와 콜리(callee)가 있습니다.

http://cr3denza.blogspot.kr/2015/03/caller-callee.html 블로그에 정리가 잘되어있으며 콜러는 리눅스 콜리는 원도우에서 사용합니다.


'보안 > System' 카테고리의 다른 글

System 디버거(de-bugger)  (0) 2018.01.25
System main함수의 인자와 시스템콜  (0) 2018.01.23
System 어셈블리어 반복문  (0) 2018.01.18
System 명령어와 분기문  (0) 2018.01.17
System 어셈블리어 사칙연산  (1) 2018.01.17
Comments