Introduction to x64
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
x64, 또는 x86-64로 알려진,은 주로 데스크탑 및 서버 컴퓨팅에 사용되는 64비트 프로세서 아키텍처입니다. Intel에서 생산한 x86 아키텍처에서 유래되었으며, 이후 AMD가 AMD64라는 이름으로 채택하였습니다. 현재 개인 컴퓨터와 서버에서 널리 사용되는 아키텍처입니다.
x64는 x86 아키텍처를 확장하여 16개의 범용 레지스터를 특징으로 하며, 이들은 rax
, rbx
, rcx
, rdx
, rbp
, rsp
, rsi
, rdi
, 그리고 r8
부터 r15
까지 레이블이 붙어 있습니다. 이들 각각은 64비트(8바이트) 값을 저장할 수 있습니다. 이러한 레지스터는 호환성과 특정 작업을 위해 32비트, 16비트 및 8비트 하위 레지스터도 가지고 있습니다.
rax
- 전통적으로 함수의 반환 값에 사용됩니다.
rbx
- 메모리 작업을 위한 기본 레지스터로 자주 사용됩니다.
rcx
- 루프 카운터로 일반적으로 사용됩니다.
rdx
- 확장된 산술 연산을 포함한 다양한 역할에 사용됩니다.
rbp
- 스택 프레임의 기본 포인터입니다.
rsp
- 스택의 맨 위를 추적하는 스택 포인터입니다.
rsi
및 rdi
- 문자열/메모리 작업에서 소스 및 대상 인덱스에 사용됩니다.
**r8
**부터 **r15
**까지 - x64에서 도입된 추가 범용 레지스터입니다.
x64 호출 규약은 운영 체제에 따라 다릅니다. 예를 들어:
Windows: 첫 번째 네 개의 매개변수는 레지스터 rcx
, rdx
, r8
, 및 **r9
**에 전달됩니다. 추가 매개변수는 스택에 푸시됩니다. 반환 값은 **rax
**에 있습니다.
System V (UNIX 유사 시스템에서 일반적으로 사용됨): 첫 번째 여섯 개의 정수 또는 포인터 매개변수는 레지스터 rdi
, rsi
, rdx
, rcx
, r8
, 및 **r9
**에 전달됩니다. 반환 값도 **rax
**에 있습니다.
함수가 여섯 개 이상의 입력을 가지면, 나머지는 스택에 전달됩니다. RSP, 스택 포인터는 16바이트 정렬되어야 하며, 이는 호출이 발생하기 전에 가리키는 주소가 16으로 나누어 떨어져야 함을 의미합니다. 이는 일반적으로 함수 호출 전에 RSP가 적절히 정렬되어야 함을 의미합니다. 그러나 실제로는 이 요구 사항이 충족되지 않더라도 시스템 호출이 여러 번 작동합니다.
Swift는 https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64에서 찾을 수 있는 자체 호출 규약을 가지고 있습니다.
x64 명령어는 풍부한 세트를 가지고 있으며, 이전 x86 명령어와의 호환성을 유지하고 새로운 명령어를 도입합니다.
mov
: 한 레지스터 또는 메모리 위치에서 다른 위치로 값을 이동합니다.
예: mov rax, rbx
— rbx
의 값을 rax
로 이동합니다.
push
및 pop
: 스택에 값을 푸시하거나 팝합니다.
예: push rax
— rax
의 값을 스택에 푸시합니다.
예: pop rax
— 스택의 맨 위 값을 rax
로 팝합니다.
add
및 sub
: 덧셈 및 뺄셈 연산입니다.
예: add rax, rcx
— rax
와 rcx
의 값을 더하여 결과를 rax
에 저장합니다.
mul
및 div
: 곱셈 및 나눗셈 연산입니다. 주의: 이들은 피연산자 사용에 대한 특정 동작을 가지고 있습니다.
call
및 ret
: 함수를 호출하고 반환하는 데 사용됩니다.
int
: 소프트웨어 인터럽트를 트리거하는 데 사용됩니다. 예: int 0x80
는 32비트 x86 Linux에서 시스템 호출에 사용되었습니다.
cmp
: 두 값을 비교하고 결과에 따라 CPU의 플래그를 설정합니다.
예: cmp rax, rdx
— rax
를 rdx
와 비교합니다.
je
, jne
, jl
, jge
, ...: 이전 cmp
또는 테스트의 결과에 따라 제어 흐름을 변경하는 조건부 점프 명령어입니다.
예: cmp rax, rdx
명령어 후, je label
— rax
가 rdx
와 같으면 label
로 점프합니다.
syscall
: 일부 x64 시스템(예: 현대 Unix)에서 시스템 호출에 사용됩니다.
sysenter
: 일부 플랫폼에서 최적화된 시스템 호출 명령어입니다.
이전 기본 포인터 푸시: push rbp
(호출자의 기본 포인터를 저장)
현재 스택 포인터를 기본 포인터로 이동: mov rbp, rsp
(현재 함수에 대한 새로운 기본 포인터 설정)
로컬 변수를 위한 스택 공간 할당: sub rsp, <size>
(여기서 <size>
는 필요한 바이트 수)
현재 기본 포인터를 스택 포인터로 이동: mov rsp, rbp
(로컬 변수 해제)
스택에서 이전 기본 포인터 팝: pop rbp
(호출자의 기본 포인터 복원)
반환: ret
(호출자에게 제어 반환)
다양한 클래스의 syscalls가 있으며, 여기에서 찾을 수 있습니다:
그런 다음, 각 syscall 번호를 이 URL에서: 찾을 수 있습니다.
그래서 Unix/BSD 클래스에서 open
시스템 호출(5)을 호출하려면 다음을 추가해야 합니다: 0x2000000
따라서 open을 호출하는 시스템 호출 번호는 0x2000005
가 됩니다.
컴파일하려면:
바이트를 추출하려면:
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)