일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 시스템 프로그래밍
- 컴퓨터구조
- 시스템해킹
- 리눅스
- Leviathan
- 프로그래밍
- css
- 시스템
- 시그널
- 리버싱
- wargame
- 리눅스커널
- 드론
- Pwnable.kr
- 어셈블리어
- write up
- 취약점
- C언어
- pwncollege
- Bandit
- px4
- 리눅스 커널
- kernel
- pwn.college
- 시스템프로그래밍
- radare2
- 커널
- 알고리즘
- 워게임
- C++
- Today
- Total
Computer Security
#16 어셈블리어-스택과 프로시저 본문
스택
-후입선출(LIFO, Last-In-First-Out) 자료구조
-스택포인터(SP, Stack Pointer)는 스택의 최상위(top) 원소를 가리키는 주소를 저장하는 레지스터
-8086은 스택 세그먼트 레지스터 SS와 스택 포인터 SP를 제공(80386+는 ESP)
-스택은 상위 주소에서 하위 주소로 거꾸로 성장함
-레지스터에 있는 데이터를 스택에 저장하는 연산을 PUSH, 스택에 저장된 데이터를 꺼내서 레지스터에 적재하는 연산을 POP이라 한다.
PUSH:스택은 상위주소에서 하위주소로 내려간다.
POP:마지막으로 들어왔던 데이터부터 꺼내서 레지스터에 적재
PUSH 명령어
-피연산자로 지정한 워드/이중워드(80386+) 크기 레지스터나 메모리 데이터를 스택에 저장한다.
-플래그:아무것도 영향을 미치지 않는다.
PUSH reg16/mem16
PUSH reg32/mem32(80386+)
POP 명령어
-피연산자로 지정한 워드/이중워드(80386+) 크기 레지스터나 메모리 공간에 스택 최상위에 저장된 데이터를 꺼내서 저장한다.
-플래그: 아무 영향 x
POP reg16/mem16
POP reg32/mem32 (80386+)
PUSHA(80286+) / PUSHAD(80386+)
-모든 범용 레지스터를 PUSH한다.
-PUSHA: AX, CX, DX, BX, SP, BP, SI, DI 를 순서대로 스택에 push 하고 SP를 16 감소시킨다.(80286+)
-PUSHAD: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI를 순서대로 스택에 push 하고 ESP를 32감소시킨다.(80386+)
-플래그: 아무 영향 x
POPA(80286+) / POPAD(80386+)
-모든 범용 레지스터를 POP한다.
-POPA: 스택 최상위에 있는 8개의 워드를 POP하여 DI, SI, BP, SP, BX, DX, CX, AX에 순서대로 넣는다.(80286+)
-POPAD: 스택 최상위에 있는 8개의 이중워드를 POP하여 EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX에 순서대로 넣는다.(80386+)
-플래그: 아무 영향 x
PUSHF/PUSHFD
-플래그를 스택에 PUSH한다.
-PUSHF:16비트 플래그 레지스터의 내용을 스택에 PUSH하고 SP를 2감소시킨다.
-PUSHFD:32비트 플래그 레지스터의 내용을 스택에 PUSH하고 ESP를 4감소시킨다.(80386+)
-플래그: 아무 영향 x
POPF/POPFD
-스택으로부터 플래그를 POP한다.
-POPF: 스택의 최상위에 있는 워드를 POP하여 16비트 플래그 레지스터에 넣고 SP를 2증가 시킨다.
-POPFD: 스택의 최상위에 있는 이중워드를 POP하여 32비트 플래그 레지스터에 넣고 SP를 4증가 시킨다.(80386+)
-플래그: 모든 플래그에 영향을 미친다.
스택의 활용
-서브루틴 호출 이후 본 프로그램으로 복귀하기 위한 복귀 주소(return address)를 저장할 때 사용된다.
-프로시저로 매개변수를 전달하는 방법 중 하나로 스택을 이용한다.
-고급언어에서 지역변수는 스택 영역에 할당된다.
-서브루틴을 호출하거나 인터럽트가 발생해서 인터럽트 서비스 루틴(ISR)이 호출되면 기존의 레지스터 값들이 변경될 수 있기 때문에 레지스터 값들을 보존할 때 스택에 저장한다.
프로시저
원래 코드를 쭉 읽다가 Call PROC(이름)을 만나면 그쪽 으로 가서 거기 실행하다가 RET(return)을 만나면 다시 원래 메모리로 돌아가서 실행하는 구조
프로시저 정의와 종료
name PROC type
,,,,
name ENDP
-name은 프로시저의 이름이다. 식별자 규칙을 따라야 한다.
-type은 프로시저의 유형이다. NEAR 또는 FAR로 지정 가능하다.
-NEAR은 세그먼트 내부에서 사용되는 근거리 프로시저를 가리킨다.
-FAR은 원거리 프로시저로, 세그먼트 밖에서도 호출 가능하다.
-type을 별도로 지정하지 않으면, NEAR 형식이 기본값으로 지정된다.
프로시저 명령어
CALL 명령어
-어셈블러는 피호출 프로시저가 NEAR이면 근거리 CALL을 사용하고, FAR이면 원거리 CALL을 생성한다.
-근거리인 경우 CALL은 IP(다음 명령어의 주소)를 스택에 푸시한다. 그 다음에 IP(Intrupt pointer)를 목적지 오프셋 주소로 적재한다.
-원거리인 경우 CALL은 CS를 스택에 푸시하고 세그먼트 간 포인터를 스택에 적재한다.
-그 다음에 IP를 푸시하고 목적지 오프셋 주소로 적재한다.
-복귀할 때 RETN과 RETF는 이 과정을 반대로 수행한다.
-플래그: 아무 영향 x
CALL reg/mem
RET/RETN/RETF
-어셈블러는 NEAR이라는 레이블이 붙은 프로시저인 경우는 근거리 RET를 생성하고, FAR이라는 레이블이 붙은 프로시저인 경우는 원거리 RET를 생성한다.
-근거리 RET는 스택의 꼭대기에 있는 워드를 IP로 옮기고 SP를 2 증가시킨다.
-원거리의 경우 RET는 스택의 꼭대기에 있는 워드들을 IP와 CS에 옮기고 SP를 4증가 시킨다.
-임의의 수치 피연산자(예를 들어 RET 4)가 SP에 더해질 수 있다.
-플래그: 아무 영향 x
RET/RETN/RETF [즉시값]
매개변수 전달
레지스터를 이용한 방법
-매개변수 전달하기 위한 방법 중 하나로 특정 레지스터를 지정하는 방법이 있다.
-레지스터 개수가 제한적이기 때문에 제약이 따른다.
레지스터를 이용하게되면
main PROC FAR
MOV DX, data 에서의 DX를
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
sub1 PROC NEAR
MOV AX, DX 여기서 불러와서도 쓸 수 있다.
스택을 이용한 방법
-프로시저를 호출하기 전에 스택에 데이터들을 push하여 매개변수를 전달하는 방법이ㅣ 있다.
-스택 포인터 SP의 값을 보존하면서도, 매개변수 접근을 위한 베이스 레지스터로 BP를 사용한다.
호출규약
-호출규약에 따라 매개변수를 전달하고 스택을 정리하는 방법이 달라진다.
-C에서 사용하는 cdecl, 윈도 API에서 주로 사용하는 stdcall 등이 존재한다.
'컴퓨터구조&어셈블리어' 카테고리의 다른 글
#17 어셈블리어 예제 (0) | 2022.06.02 |
---|---|
#15 어셈블리 - 분기명령어 (0) | 2022.05.29 |
#14 산술 및 논리 연산 명령어2 (0) | 2022.05.28 |
#13 산술 및 논리 연산 명령어1 (0) | 2022.05.27 |
#12 컴퓨터의 데이터표현 2 (0) | 2022.05.26 |