Skip to content

Latest commit

 

History

History
118 lines (80 loc) · 5.05 KB

direct-and-indirect-syscalls.md

File metadata and controls

118 lines (80 loc) · 5.05 KB
description cover coverY layout
06/09/2024
../../.gitbook/assets/Screenshot 2024-06-09 at 1.15.47 AM.png
0
cover title description tableOfContents outline pagination
visible size
true
full
visible
true
visible
true
visible
true
visible
true
visible
true

Direct & Indirect Syscalls

Introduction

As previously mentioned, syscalls are mechanisms that allow user-accessed and controlled applications to request services from the OS's kernel. There are two main methods for making syscalls.

  1. Direct
  2. Indirect

{% embed url="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Priv_rings.svg/600px-Priv_rings.svg.png" fullWidth="false" %} There's lots of talk between user-land and kernel-land. Hopefully this clears it up. Also, you may hear me addressing various layers as "rings". {% endembed %}

Direct Syscalls

This method involves the application making a direct call to the kernel using the corresponding syscall number. Remember, this syscall number is a unique identifier for the service/function requested from the underlying kernel. Direct syscalls are implemented directly through Assembly code via Assembly instructions.

How Direct Syscalls Work

Direct syscalls work by preparing arguments for the syscall within the specific numbers that are required by the syscall convention for the corresponding architecture. Be sure to follow the link above for abiding by the convention.

Next, load the syscall number into the specific register.

Next, trigger the syscall using a special instruction or a software interrupt, this will transition control to the kernel. User-mode -> Kernel-mode.

Kernel Execution: The kernel will then catch the interrupt or special instruction, perform a lookup on the syscall number received, and execute the kernel function from the corresponding syscall number.

Lastly, the kernel function will return to user-mode the moment the kernel-level function completes its work.

Example

// connect(sockfd, &sockaddr, 16)
        mov   x0, x4            // sockfd
        adr   x1, sockaddr      // pointer to address, port
        mov   x2, #16
        mov   w8, #203          // x8 = 203 (connect)
        svc   #0                // call syscall -> kernel-mode

Indirect Syscalls

An indirect syscall will involve an intermediary, such as a dynamic linker or a library that will abstract the details of making the syscall; hence, indirect. However, the syscalls origins and underlying implementations are still occurring, just abstracted.

🚨 This is why malware loves indirect syscalls. These are "hard" to keep track of.

How Indirect Syscalls Work

First, the application call will perform a high-level function provided by a library (libc).

Next, the library function within library code will prepare the arguments and perform the duties of the direct syscall on behalf of the user-controlled application.

Syscall Execution: The direct syscall is executed as described in the direct syscall section.

Return to Application: The result is returned to the library function, which may process it further before returning it to the application.

Example

Here is an example C program that uses the libc library to write to the STDOUT file descriptor and exit.

example.c:

#include <unistd.h>
#include <stdlib.h>

int main() {
    const char *msg = "Hello, World!\n";
    write(STDOUT_FILENO, msg, 14);  // Indirect syscall to sys_write
    exit(EXIT_SUCCESS);             // Indirect syscall to sys_exit
}

Explanation

write is a high-level, abstracted function, that is provided by libc that performs the write syscall.

{% embed url="https://man7.org/linux/man-pages/man2/write.2.html" %} Documentation {% endembed %}

exit is another, that is provided by the libc library that internally handles and performs the exit syscall.

{% embed url="https://man7.org/linux/man-pages/man2/exit.2.html" %} Documentation {% endembed %}

Differences

Direct syscalls are way more efficient because there is no intermediary layer and can be called, well, directly. However, a deeper knowledge and understanding of lower-level technologies is required.

Indirect syscalls are easier to use because they are provided by abstracted higher-level libraries such as libc. This will require additional performance overhead, compared to direct Assembly syscall functionality.

References

{% embed url="https://redops.at/en/blog/direct-syscalls-vs-indirect-syscalls" %} Awesome Read {% endembed %}