64bit 全盛期に需要はないでしょうが…
とりあえずのメモです。需要がありそうなら、修正していきます。
筆者が試した環境
- VMware(R) Workstation 16 Player
- kali-linux-2023.4-vmware-i386
- NASM version 2.16.01
要点
- 32bit アーキテクチャでは、本来は、kernel が vdso (virtual dynamic shared object) という仕組みを利用して、ユーザープロセスに注入する __kernel_vsyscall を通じてシステムコールを呼ぶのが筋
- sysenter 呼ぶ前にやるべきこと
- sysenter からの戻り先を保存(push sysenter_ret)
- レジスタ ECX の保存(push ecx)
- レジスタ EDX の保存(push edx)
- レジスタ EBP の保存(push ebp)
- レジスタ EBP に ESP の値を移動(mov ebp, esp)
コード例(nasm版 Intel 記法)
gas 版(AT&T 記法)は、assembly - How to use sysenter under Linux? - Reverse Engineering Stack Exchange を参照
section .data
msg db "Hello World!", 0x0a
len equ $ - msg
section .text
global _start
_start:
mov edx, len ; size_t count
mov ecx, msg ; const char *buf
mov ebx, 1 ; unsigned int fd
mov eax, 4 ; write システムコール
push sysenter_ret ; sysenter からの戻り先を保存
push ecx ; レジスタ ECX の保存
push edx ; レジスタ EDX の保存
push ebp ; レジスタ EBP の保存
mov ebp, esp ; レジスタ EBP に ESP の値を移動(複写)
sysenter
sysenter_ret:
mov ebx, 0 ; error_code
mov eax, 1 ; exit システムコール
push sysenter_ret
push ecx
push edx
push ebp
mov ebp, esp
sysenter
ビルド・実行は次の手順で行う。(上記ソースファイル名を sysenter.s とした場合)
$ nasm -f elf32 sysenter.s
$ ld -o sysenter sysenter.o
$ ./sysenter
Hello World! ← 実行結果
Makefile 作るなら
sysenter: sysenter.o
ld -o $@ $<
sysenter.o: sysenter.s
nasm -f elf32 $<
clean:
rm -f sysenter sysenter.o