본문 바로가기
Study Log/정보 보안

[정보 보안] 6. 어셈블리 언어 Part.3

by LOGER 2023. 9. 19.

스택과 함수

스택

- 후입선출의 특성을 가진 자료구조
- 나중에 들어온 데이터가 먼저 나감 (LIFO, Last - in - First - out)
- push 연산으로 데이터를 스택에 넣음
- pop 연산으로 데이터를 꺼냄
- 주소상으로 윗부분이 낮은 주소가 됨
 
push [피연산자 1]
- 스택의 최상단에 피연산자 1 삽입
- 스택포인터 감소함 (32bit -> 4, 64bit -> 8)
- 피연산자 1에 레지스터, 메모리, 상수 모두 가능
 
pop [피연산자 1]
- 스택의 최상단에 피연산자 1 로 로드 (가져옴)
- 스택포인터 증가함 (32bit -> 4, 64bit -> 8)
- 피연산자 1에 레지스터, 메모리 가능
 
call [피연산자 1]
- 함수호출 (피연산자 1로 이동)
- jmp는 단순이동, call은 복귀 주소를 스택에 넣고 이동
 
복귀함수 (return address)
- 함수의 호출이 끝난 뒤 다시 돌아올 주소를 저장하는 스택 주소
 
 
 

함수의 프롤로그

push rbp
- SFP (Saved Frame Pointer) 저장 명령어
- main 함수가 끝나고 rbp를 복구하기 위해서
 
mov rbp, rsp
- 밑에 있던 rbp를 위로 올림 (이전 rbp 값 백업)
 
sub rsp, 10h
- 스택공간 2개를 확보함
 
 

함수의 에필로그

leave

- 스택 프레임을 정리
push rsp, rbp
- rbp, rsp가 같은 주소 가르킴 (기존의 확보해놓은 공간 없어짐)
pop rbp
- 기존 rbp값으로 복구됨
 

ret

- return address로 복귀
- 함수끝에는 무조건 이 명령어가 존재함
pop rip
- 해당 주소가 rip에 들어감
 
실제로 함수를 실행할 때는 어떠한 다른 함수에서 main을 실행하기에 ret로 스택이 시작함
 
 

기타 명령어

xchg [피연산자 1] [피연산자 2]
- 피연산자 1, 2의 값을 교환한다
- 레지스터나 메모리만 가능
 
movzx [피연산자 1] [피연산자 2]
- 피연산자 2를 1로 이동하고 나머지 비트를 0으로 채운다
- 피연산자 2가 양수여야 하고, 1보다 작아야 한다. (작은 데이터를 큰 공간으로 옮긴다)
- 피연산자 2에는 1,2바이트 크기의 레지스터 또는 메모리만 올 수 있음 (굳이 4바이트를 8바이트로 옮길필요 없음)
 
movsx [피연산자 1] [피연산자 2]
- 피연산자 2를 1로 이동하고 나머지 비트를 1로 채운다
- 피연산자 2가 음수여야 하고, 1보다 작아야 한다. (작은 데이터를 큰 공간으로 옮긴다)
- 피연산자 2에는 4바이트 크기도 이동 가능
 
nop
- 아무 역할도 없음
- 코드패치 (원치 않는 명령을 이 명령으로 변경 함), 셸 코드를 사용할 때 사용
 

시스템 콜

- 커널이 제공하는 서비스에 접근하기 위한 인터페이스
- 프로세스, 파일, 장치, 정보, 통신, 보안 등의 기능은 사용자 프로세스에서 실행 불가 (보안 이슈)
- 그래서 사용자 프로세스가 아닌 커널에서 실행해줌
ex) printf, scanf 등
 
시스템 콜에는 번호가 할당 됨
 
int 0x80
- x86에서 시스템 콜을 호출하는 명령
- 시스템 콜 호출 이전 시스템 콜 번호와 인자들 세팅 필요
- x86에서 eax에 시스템 콜 번호
- 인자에는 ebx, ecx, edx, esi, edi, ebp
- 시스템 콜의 최대 인자는 6개
 
** esp는 망가지면 안됨으로 사용 안함
 
syscall
- x86_64에서 시스템 콜 호출 명령
- 시스템 콜 호출 이전 시스템 콜 번호와 인자들 세팅 필요
- x86_64에서 rax에 시스템 콜 번호
- 인자는 rdi, rsi, rdx, r10, r8, r9