농소
프로세스 메모리 구조, 스택 레지스터, 함수 본문
프로세스 메모리 구조
우선 메모리 구조를 확인하기 위해서 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
'Security > System Hacking' 카테고리의 다른 글
시스템 프로그래밍, 시스템 콜 (0) | 2018.01.25 |
---|---|
asm 지역변수 배열, main 함수의 인자 int argc, char *argv[ ] (0) | 2018.01.24 |
nasm 반복문 연습2 (0) | 2018.01.20 |
nasm 반복문 연습 (0) | 2018.01.19 |
asm 형변환, 관계연산, 제어문 (0) | 2018.01.18 |