mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 19:21:15 +07:00
fix
This commit is contained in:
parent
ed53b050d2
commit
cc7972dc50
@ -112,9 +112,76 @@ exit(0) = ?
|
||||
```
|
||||
可以看到程序将调用号保存到 `eax`,并通过 `int $0x80` 来使用系统调用。
|
||||
|
||||
虽然软中断 `int 0x80` 非常经典,早期 2.6 及以前版本的内核都使用这种机制进行系统调用。但因其性能较差,在往后的内核中使用了快速系统调用指令来替代,32 位系统使用 `sysenter` 指令,而 64 位系统使用 `syscall` 指令。
|
||||
虽然软中断 `int 0x80` 非常经典,早期 2.6 及以前版本的内核都使用这种机制进行系统调用。但因其性能较差,在往后的内核中使用了快速系统调用指令来替代,32 位系统使用 `sysenter`(对应`sysexit`) 指令,而 64 位系统使用 `syscall`(对应`sysret`) 指令。
|
||||
|
||||
下面是一个 64 位的例子:
|
||||
一个使用 sysenter 的例子:
|
||||
```
|
||||
.data
|
||||
|
||||
msg:
|
||||
.ascii "Hello sysenter!\n"
|
||||
len = . - msg
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
movl $len, %edx
|
||||
movl $msg, %ecx
|
||||
movl $1, %ebx
|
||||
movl $4, %eax
|
||||
# Setting the stack for the systenter
|
||||
pushl $sysenter_ret
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
sysenter
|
||||
|
||||
sysenter_ret:
|
||||
movl $0, %ebx
|
||||
movl $1, %eax
|
||||
# Setting the stack for the systenter
|
||||
pushl $sysenter_ret
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
sysenter
|
||||
```
|
||||
```
|
||||
$ gcc -m32 -c sysenter.S
|
||||
$ ld -m elf_i386 -o sysenter sysenter.o
|
||||
$ strace ./sysenter
|
||||
execve("./sysenter", ["./sysenter"], 0x7fff73993fd0 /* 69 vars */) = 0
|
||||
strace: [ Process PID=7663 runs in 32 bit mode. ]
|
||||
write(1, "Hello sysenter!\n", 16Hello sysenter!
|
||||
) = 16
|
||||
exit(0) = ?
|
||||
+++ exited with 0 +++
|
||||
```
|
||||
可以看到,为了使用 sysenter 指令,需要为其手动布置栈。这是因为在 sysenter 返回时,会执行 `__kernel_vsyscall` 的后半部分(从0xf7fd5059开始):
|
||||
```
|
||||
gdb-peda$ vmmap vdso
|
||||
Start End Perm Name
|
||||
0xf7fd4000 0xf7fd6000 r-xp [vdso]
|
||||
gdb-peda$ disassemble __kernel_vsyscall
|
||||
Dump of assembler code for function __kernel_vsyscall:
|
||||
0xf7fd5050 <+0>: push ecx
|
||||
0xf7fd5051 <+1>: push edx
|
||||
0xf7fd5052 <+2>: push ebp
|
||||
0xf7fd5053 <+3>: mov ebp,esp
|
||||
0xf7fd5055 <+5>: sysenter
|
||||
0xf7fd5057 <+7>: int 0x80
|
||||
0xf7fd5059 <+9>: pop ebp
|
||||
0xf7fd505a <+10>: pop edx
|
||||
0xf7fd505b <+11>: pop ecx
|
||||
0xf7fd505c <+12>: ret
|
||||
End of assembler dump.
|
||||
```
|
||||
`__kernel_vsyscall` 封装了 sysenter 调用的规范,是 vDSO 的一部分,而 vDSO 允许程序在用户层中执行内核代码。关于 vDSO 的内容我们将在后面的章节中细讲。
|
||||
|
||||
下面是一个 64 位使用 `syscall` 的例子:
|
||||
```
|
||||
.data
|
||||
|
||||
|
@ -6,9 +6,23 @@
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
|
||||
在章节 1.5.9 中我们介绍了 Linux 系统调用的知识。这一节中将了解 `vsyscall` 和 `vDSO` 两种机制,它们被设计用来加速系统调用的处理。
|
||||
|
||||
## vsyscall
|
||||
```
|
||||
$ cat /proc/self/maps | grep vsyscall
|
||||
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
|
||||
```
|
||||
|
||||
|
||||
## vDSO
|
||||
```
|
||||
$ cat /proc/self/maps | grep vdso
|
||||
7fff223aa000-7fff223ac000 r-xp 00000000 00:00 0 [vdso]
|
||||
$ cat /proc/self/maps | grep vdso
|
||||
7fff1048f000-7fff10491000 r-xp 00000000 00:00 0 [vdso]
|
||||
```
|
||||
|
||||
|
||||
## CTF 实例
|
||||
例如章节 6.1.6 的 ret2vdso。
|
||||
|
32
src/others/1.5.9_linux_kernel/sysenter.S
Normal file
32
src/others/1.5.9_linux_kernel/sysenter.S
Normal file
@ -0,0 +1,32 @@
|
||||
.data
|
||||
|
||||
msg:
|
||||
.ascii "Hello sysenter!\n"
|
||||
len = . - msg
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
movl $len, %edx
|
||||
movl $msg, %ecx
|
||||
movl $1, %ebx
|
||||
movl $4, %eax
|
||||
|
||||
pushl $sysenter_ret
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
sysenter
|
||||
|
||||
sysenter_ret:
|
||||
movl $0, %ebx
|
||||
movl $1, %eax
|
||||
|
||||
pushl $sysenter_ret
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
sysenter
|
Loading…
Reference in New Issue
Block a user