** Register

위 어셈블리어 코드에서는 크게 data 영역과 text 영역으로 나누었다.
data 영역에서는 Hello world라는 문자열을 담는 msg라는 이름의 변수를 만들어주었고,
실제로 코드를 실행하는 text 영역에서 msg 변수를 사용한 걸 볼 수 있다.
이제 이러한 코드가 어떻게 동작하는지 이해하기 위해 64bit 운영체제 상에서 동작하는 갖가지 레지스터의 이름, 쓰임새와
그러한 레지스터가 실질적으로 사용되기 위해 알아야하는 system call 개념에 대해 배울 것이다.
https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture
x64 Architecture - Windows drivers
The x64 architecture is a backwards-compatible extension of x86. It provides a legacy 32-bit mode, which is identical to x86, and a new 64-bit mode.
learn.microsoft.com
마이크로소프트에서 공식 문서로 제공해주는 64-bit architecture

bit별로 레지스터를 보여주고있다. 과거 32 bit 운영체제에서는 앞에 e로 시작하는 레지스터를 사용하곤 했다.
지금은 CPU가 한 번에 처리하는 단위가 64 bit로 늘어났기 때문에 앞에 r이 붙은 형식으로 레지스터 이름이 바뀌었다.
예를 들어
| rax | 시스템 콜의 실질적인 번호를 가리키는 레지스터이자, 함수가 실행된 다음 결과가 담기는 레지스터 |
| rbx | base register로, 메모리 주소를 지정할 때 사용한다. |
| rcx | count register로, 주로 반복문에 많이 사용된다. |
| rdx | data register로, 연산을 수행할 때 rax와 함께 많이 사용된다. |
위 4가지를 데이터 레지스터로 분류한다.
그 다음 아래의 4가지 레지스터는 포인터 레지스터이다.
| rsi | 메모리를 이동하거나 비교할 때 출발지 주소를 가리킨다. |
| rdi | 메모리를 이동하거나 비교할 때 목적지 주소를 가리킨다. |
| rbp | 함수의 파라미터나 변수의 주소를 가리킬때 많이 사용한다. |
| rsp | 어떠한 스택이 있을때, 그 스택에 삽입 및 삭제 명령에 의해서 변경되는 스택에서 가장 위에 있는 주소를 가리키는 register |
r8부터 r15도 쓰임새가 존재하는데, 일반적으로 함수의 매개변수로 사용이 된다.
이러한 레지스터를 통해 어셈블리어 코딩을 할 수 있다.
** System Call
구글에 64bit systecm call table 입력하면 정보 많음.
그 중 하나
https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
Linux System Call Table for x86 64 · Ryan A. Chapman
Linux 4.7 (pulled from github.com/torvalds/linux on Jul 20 2016), x86_64 Note: 64-bit x86 uses syscall instead of interrupt 0x80. The result value will be in %rax To find the implementation of a system call, grep the kernel tree for SYSCALL_DEFINE.\?(sysca
blog.rchapman.org

0번 시스템 콜 함수는 sys_read
1번 시스템 콜 함수는 sys_write
이런 식으로 각각 다양한 함수들이 기본적으로 커널 단에 마련이 되어있다.
%rax가 앞서서 시스템 콜 함수를 불러올 때 그 번호를 가리키는데, 만약 시스템 콜을 불러오기 전에 rax에 0이란 값이 담겨있다면 sys_read 함수를 사용한다.
갖가지 함수들에는 기본적으로 매개 변수가 따라오는데 대표적인 예로
sys_write 함수
- %rdi가 fd(file descripter) 역할을 하는 것을 알 수 있다.
- 컴퓨터에 내용을 출력(write)하는 함수이므로 정확히 어떠한 문자열을 출력할지, 그에 대한 문자열을 %rsi가 포함하게 한다.
- 출력한 문자열의 길이는 %rdx에 담아 함수를 불러온다.
실제로 코딩할 때 시스템 콜 테이블을 두고 참고해서 다양한 함수를 불러올 수 있고, 기존 C언어나 자바같은 고급 언어에 비해 훨씬 빠르게 동작하는 프로그램을 작성할 수 있다.
section .data
msg db "Hello World"
→ data 영역에 Hello world라는 문자열을 만들어놓고, 그 문자열의 위치를 가리키는 포인터 msg를 하나의 변수로써 마련한 다음
section .text
global_start
_start:
→ text 영역에 가장 처음으로 실행되는 start 함수를 정의한다.
mov rax, 1
→ rax에 1을 담음으로써, sys_write 를 불러올거라고 컴퓨터에게 알려준다.
mov rdi, 1
→ rdi, 즉 파일 디스크럽터에 1을 입력해 어떠한 문자열을 출력하겠다고 syscall 함수의 매개변수로 넣어준다.
mov rsi, msg
→ 어떠한 문자열을 출력할건지 msg라는 포인터 변수를 rsi 값에 넣어줌으로써 Hello World가 출력될 수 있게 한다.
mov rdx, 12
→ Hello World를 모두 출력할 수 있는 충분한 길이인 12을 넣어줌으로써 하나의 Systemcall을 불러올 준비를 마쳤다.
syscall
→ 결과적으로 system call을 불러옴으로써 Hello world가 콘솔창에 출력된다.
밑에 있는 코드는 무엇일까?
mov rax, 60
mov rdi, 0
syscall
60은 sys_exit이라는 걸 알 수 있고, rdi에는 error 코드를 매개변수로 넣는다.

rdi에 0을 넣어주면서 코드가 안전하게 종료될 수 있도록 한다.
즉, 첫 번째 시스템콜은 Hello World를 출력해주는 콜, 두 번째 시스템콜은 프로그램을 종료하는 시스템 콜이다.
'공부중 > 시스템 해킹' 카테고리의 다른 글
| [Dreamhack] Linux memory Layout (0) | 2024.09.09 |
|---|---|
| [Dreamhack]x86-64 아키텍처 (0) | 2024.09.09 |
| 윈도우 환경 구축/WSL2 (0) | 2024.07.13 |
| 리눅스<>로컬 pc ssh 연결 (0) | 2024.06.30 |
| 메모리 구조 이해하기 (0) | 2024.03.02 |
댓글