본문으로 바로가기

어셈블리에서의 함수 및 메모리 구조1

category Pwnable 2018. 7. 30. 10:57

어셈블리언어의 함수


- 함수(function)라는 개념이 없다.

- 스택 메모리를 이용하여 함수를 대체한다.



간단히 아래의 소스를 작성해보자.



1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int main()
{
    printf("hello, world\n");
    sleep(1000000);
 
    return 0;
}
cs



아래와 같이 컴파일 후 Ctrl + Z를 통해 프로세스를 중지시킨다.





sample의 프로세스가 중지되었고 pid는 892이다.





/proc/ 디렉토리에 현재 실행 중인 프로세스의 pid 이름으로 디렉토리가 생성된다.

우리가 살펴볼 sample의 pid는 892이고 892 이름의 디렉토리가 있다는 것을 확인할 수 있다.


892 디렉토리로 이동하면 maps라는 파일이 보이는데 maps 는 프로세스가 사용하는 전체 메모리를 보여준다.

sample은 0x08048000 ~ 0xc0000000 영역의 메로리를 사용한다. 

0xc0000000 - 0x08048000 = 0xB7FB8000 으로 약 3G 정도의 메모리를 사용한다.




우리가 모두 알다시피 스택높은 메모리에서 낮은 메모리로 쌓이는 구조를 가진다.

주소가 점점 줄어들면서 메모리가 사용된다.


stack - 밑에서부터 쌓아 올라가기 때문에 stack이란 이름이 붙었다.


push를 하면 stack에 쌓인다. 기본적으로 stack은 4byte 씩 쌓인다.

argument를 전달할 때 stack을 이용해서 전달한다.


pop을 이용해서 stack에 값을 꺼내온다.

나중 데이터부터(낮은 메모리 부터) 차례대로 값을 꺼낸다.


stack구조를 lifo(last input first out)구조라고 부른다.

esp(stack pointer)라는 레지스터가 stack 영역의 top을 가리킨다.

ebp(base pointer)라는 레지스터가 stack 영역의 bottom을 가리킨다.




위와 같이 push를 할 때마다 메모리가 4byte 씩 감소하는 것을 확인 할 수 있다.



예제 1) 아래의 소스를 어셈블리어로 작성하시오.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
int result = 0;
int a,b;
 
int sum(int a, int b)
{
    return a + b;
}
 
int main()
{
    result = sum( 1020 );
    printf("sum : %d\n", result);
    return 0;
}
cs



좋지 않은 어셈블리어 프로그래밍


- 아래와 같이 작성하면 함수가 많을 수록 너무 복잡해 진다.




좋은 어셈블리 프로그래밍1


- eip(instruction pointer)를 사용한다. eip란 다음 실행될 명령어의 위치이다.

cpu는 항상 eip를 가져와 명령어를 수행한다.





좋은 어셈블리 프로그래밍 2


- return(ret) 값은 eax를 통해 return 된다.

- 함수의 프롤로그와 에필로그를 사용해서 프로그래밍한다.