LegionMammal978

Look ma, no writes!

Sep 28th, 2022 (edited)
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.88 KB | None | 0 0
  1. #define _GNU_SOURCE
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <stdnoreturn.h>
  7. #include <sys/socket.h>
  8. #include <sys/socket.h>
  9. #include <sys/stat.h>
  10. #include <sys/syscall.h>
  11. #include <unistd.h>
  12.  
  13. #define BPF_LD 0x00
  14. #define BPF_ALU 0x04
  15. #define BPF_RET 0x06
  16.  
  17. #define BPF_B 0x10
  18.  
  19. #define BPF_ABS 0x20
  20.  
  21. #define BPF_ADD 0x00
  22.  
  23. #define BPF_K 0x00
  24. #define BPF_A 0x10
  25.  
  26. struct sock_filter {
  27.     uint16_t code;
  28.     uint8_t jt;
  29.     uint8_t jf;
  30.     uint32_t k;
  31. };
  32.  
  33. struct sock_fprog {
  34.     unsigned short len;
  35.     struct sock_filter *filter;
  36. };
  37.  
  38. #define ERR ((uint64_t)-4096)
  39.  
  40. static uint64_t syscall0(uint64_t no) {
  41.     uint64_t result;
  42.     __asm__ volatile(
  43.         "syscall"
  44.         : "=a" (result)
  45.         : "a" (no)
  46.         : "rcx", "r11"
  47.     );
  48.     return result;
  49. }
  50.  
  51. static uint64_t syscall1(uint64_t no, uint64_t arg0) {
  52.     uint64_t result;
  53.     __asm__ volatile(
  54.         "syscall"
  55.         : "=a" (result)
  56.         : "a" (no), "D" (arg0)
  57.         : "rcx", "r11"
  58.     );
  59.     return result;
  60. }
  61.  
  62. static uint64_t syscall2(uint64_t no, uint64_t arg0, uint64_t arg1) {
  63.     uint64_t result;
  64.     __asm__ volatile(
  65.         "syscall"
  66.         : "=a" (result)
  67.         : "a" (no), "D" (arg0), "S" (arg1)
  68.         : "rcx", "r11"
  69.     );
  70.     return result;
  71. }
  72.  
  73. static uint64_t syscall3(uint64_t no, uint64_t arg0, uint64_t arg1, uint64_t arg2) {
  74.     uint64_t result;
  75.     __asm__ volatile(
  76.         "syscall"
  77.         : "=a" (result)
  78.         : "a" (no), "D" (arg0), "S" (arg1), "d" (arg2)
  79.         : "rcx", "r11"
  80.     );
  81.     return result;
  82. }
  83.  
  84. static uint64_t syscall5(uint64_t no, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) {
  85.     uint64_t result;
  86.     register uint64_t r10 __asm__("r10") = arg3;
  87.     register uint64_t r8 __asm__("r8") = arg4;
  88.     __asm__ volatile(
  89.         "syscall"
  90.         : "=a" (result)
  91.         : "a" (no), "D" (arg0), "S" (arg1), "d" (arg2), "r" (r10), "r" (r8)
  92.         : "rcx", "r11"
  93.     );
  94.     return result;
  95. }
  96.  
  97. static uint64_t syscall6(uint64_t no, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
  98.     uint64_t result;
  99.     register uint64_t r10 __asm__("r10") = arg3;
  100.     register uint64_t r8 __asm__("r8") = arg4;
  101.     register uint64_t r9 __asm__("r9") = arg5;
  102.     __asm__ volatile(
  103.         "syscall"
  104.         : "=a" (result)
  105.         : "a" (no), "D" (arg0), "S" (arg1), "d" (arg2), "r" (r10), "r" (r8), "r" (r9)
  106.         : "rcx", "r11"
  107.     );
  108.     return result;
  109. }
  110.  
  111. static noreturn void do_exit(int status) {
  112.     syscall1(SYS_exit_group, status);
  113.     __builtin_unreachable();
  114. }
  115.  
  116. static noreturn void do_err(uint64_t result) {
  117. #ifdef DEBUG
  118.     errno = -result;
  119.     perror(NULL);
  120. #else
  121.     (void)result;
  122. #endif
  123.     do_exit(-1);
  124. }
  125.  
  126. static int create_pipe(void) {
  127.     static const char PATHNAME[] = "/tmp/.anon-fifo";
  128.     uint64_t result;
  129.     while ((result = syscall2(SYS_mknod, (uintptr_t)PATHNAME, S_IFIFO|S_IRUSR|S_IWUSR)) != 0) {
  130.         if (result != (uint64_t)-EEXIST) {
  131.             do_err(result);
  132.         }
  133.         syscall0(SYS_sched_yield);
  134.     }
  135.     if ((result = syscall2(SYS_open, (uintptr_t)PATHNAME, O_RDWR|O_CLOEXEC)) > ERR) {
  136.         syscall1(SYS_unlink, (uintptr_t)PATHNAME);
  137.         do_err(result);
  138.     }
  139.     int pipefd = result;
  140.     if ((result = syscall1(SYS_unlink, (uintptr_t)PATHNAME)) != 0) {
  141.         syscall1(SYS_close, pipefd);
  142.         do_err(result);
  143.     }
  144.     return pipefd;
  145. }
  146.  
  147. static void stdin_to_pipe(int pipefd) {
  148.     uint64_t result;
  149.     if ((result = syscall6(SYS_splice, STDIN_FILENO, 0, pipefd, 0, 1, 0)) == 0) {
  150.         if ((result = syscall1(SYS_close, pipefd)) != 0) {
  151.             do_err(result);
  152.         }
  153.         do_exit(-1);
  154.     } else if (result != 1) {
  155.         syscall1(SYS_close, pipefd);
  156.         do_err(result);
  157.     }
  158. }
  159.  
  160. static int create_socket(int pipefd) {
  161.     static const struct sock_filter FILTER[] = {
  162.         {BPF_LD|BPF_B|BPF_ABS, 0, 0, 0},
  163.         {BPF_ALU|BPF_ADD|BPF_K, 0, 0, 1},
  164.         {BPF_RET|BPF_A, 0, 0, 0}
  165.     };
  166.     static const struct sock_fprog FPROG = {3, (struct sock_filter *)FILTER};
  167.     static const struct {
  168.         sa_family_t sa_family;
  169.         char sa_data[16];
  170.     } ADDR = {AF_UNIX, "/tmp/.anon-sock"};
  171.     uint64_t result;
  172.     if ((result = syscall3(SYS_socket, AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) > ERR) {
  173.         syscall1(SYS_close, pipefd);
  174.         do_err(result);
  175.     }
  176.     int sockfd = result;
  177.     if ((result = syscall5(SYS_setsockopt, sockfd, SOL_SOCKET, SO_ATTACH_FILTER, (uintptr_t)&FPROG, sizeof(struct sock_fprog))) != 0) {
  178.         syscall1(SYS_close, sockfd);
  179.         syscall1(SYS_close, pipefd);
  180.         do_err(result);
  181.     }
  182.     while ((result = syscall3(SYS_bind, sockfd, (uintptr_t)&ADDR, sizeof ADDR)) != 0) {
  183.         if (result != (uint64_t)-EADDRINUSE) {
  184.             syscall1(SYS_close, sockfd);
  185.             syscall1(SYS_close, pipefd);
  186.             do_err(result);
  187.         }
  188.         syscall0(SYS_sched_yield);
  189.     }
  190.     if ((result = syscall3(SYS_connect, sockfd, (uintptr_t)&ADDR, sizeof ADDR)) != 0) {
  191.         syscall1(SYS_unlink, (uintptr_t)&ADDR.sa_data);
  192.         syscall1(SYS_close, sockfd);
  193.         syscall1(SYS_close, pipefd);
  194.         do_err(result);
  195.     }
  196.     if ((result = syscall1(SYS_unlink, (uintptr_t)&ADDR.sa_data)) != 0) {
  197.         syscall1(SYS_close, sockfd);
  198.         syscall1(SYS_close, pipefd);
  199.         do_err(result);
  200.     }
  201.     return sockfd;
  202. }
  203.  
  204. static void pipe_to_socket(int pipefd, int sockfd) {
  205.     static const char PADDING[255] = {0};
  206.     uint64_t result;
  207.     if ((result = syscall3(SYS_write, pipefd, (uintptr_t)PADDING, 255)) != 255) {
  208.         syscall1(SYS_close, sockfd);
  209.         syscall1(SYS_close, pipefd);
  210.         do_err(result > ERR ? result : (uint64_t)-EIO);
  211.     }
  212.     if ((result = syscall6(SYS_splice, pipefd, 0, sockfd, 0, 256, 0)) != 256) {
  213.         syscall1(SYS_close, sockfd);
  214.         syscall1(SYS_close, pipefd);
  215.         do_err(result > ERR ? result : (uint64_t)-EIO);
  216.     }
  217. }
  218.  
  219. static unsigned char read_from_socket(int pipefd, int sockfd) {
  220.     uint64_t result;
  221.     if ((result = syscall6(SYS_splice, sockfd, 0, pipefd, 0, 256, 0)) == 0 || result > ERR) {
  222.         syscall1(SYS_close, sockfd);
  223.         syscall1(SYS_close, pipefd);
  224.         do_err(result != 0 ? result : (uint64_t)-EIO);
  225.     }
  226.     return result - 1;
  227. }
  228.  
  229. static void close_fds(int pipefd, int sockfd) {
  230.     uint64_t result;
  231.     if ((result = syscall1(SYS_close, sockfd)) != 0) {
  232.         syscall1(SYS_close, pipefd);
  233.         do_err(result);
  234.     }
  235.     if ((result = syscall1(SYS_close, pipefd)) != 0) {
  236.         do_err(result);
  237.     }
  238. }
  239.  
  240. int main(void) {
  241.     int pipefd = create_pipe();
  242.     stdin_to_pipe(pipefd);
  243.     int sockfd = create_socket(pipefd);
  244.     pipe_to_socket(pipefd, sockfd);
  245.     unsigned char c = read_from_socket(pipefd, sockfd);
  246.     close_fds(pipefd, sockfd);
  247.     do_exit(c);
  248. }
  249.  
Advertisement
Add Comment
Please, Sign In to add comment