Skip to main content
added 502 characters in body
Source Link
bishop
  • 3.2k
  • 2
  • 18
  • 31
find / -inum 242 -exec {} \; -quit

Performance motivated the question, though, and the above is not performant:. Not only is the directory structure walked to find a file having that inode (and there may be multiple), but under the hood, the inode number is resolved to a path, and the path is given to the kernel to execute. But why?

 

Since performance motivated the questionHowever, there exists a fiddly and not guaranteed to work in all environments mechanism, but that allows you to invoke a program from within memoryfrom within memory. Since anything in memory is necessarynecessarily faster than anything on disk, this drives to the heart of the question: how to run a program as fast as possible.

So, finally, if your Linux system meets the requirements above, then the things you need to do arecan execute code from within memory by:

  1. LoadLoading the code into memory somewhere. Malicious actors will have already side-loaded the desired code into memory as part of the initial drop, but if you wanted to do it along the lines of inode, you could do find / -inum 242 -exec cat {} \;
  2. InvokeInvoking the userland exec mechanism, setting its entry point to the address of memory where you stored your program from step 1
  3. Profit

The kernel, filesystem, and shell have all been tuned to make the lookup and execution of programs a negligible fraction of the total overhead necessary to do work. Loading a program in memory and executing it from there is not really in the domain of the average use case, so unless doing this for fun I'd say you'd want to benchmark the performance before investing time in trying.

find / -inum 242 -exec {} \;

Performance motivated the question, though, and the above is not performant: under the hood, the inode number is resolved to a path, and the path is given to the kernel to execute. But why?

Since performance motivated the question, there exists a fiddly and not guaranteed to work in all environments mechanism, but allows you to invoke a program from within memory. Since anything in memory is necessary faster than anything on disk, this drives to the heart of the question.

So, finally, if your Linux system meets the requirements above, then the things you need to do are:

  1. Load the code into memory somewhere. Malicious actors will have already side-loaded the desired code into memory as part of the initial drop, but if you wanted to do it along the lines of inode, you could do find / -inum 242 -exec cat {} \;
  2. Invoke the userland exec mechanism, setting its entry point to the address of memory where you stored your program from step 1
  3. Profit
find / -inum 242 -exec {} \; -quit

Performance motivated the question, though, and the above is not performant. Not only is the directory structure walked to find a file having that inode (and there may be multiple), but under the hood, the inode number is resolved to a path, and the path is given to the kernel to execute. But why?

 

However, there exists a fiddly and not guaranteed to work in all environments mechanism that allows you to invoke a program from within memory. Since anything in memory is necessarily faster than anything on disk, this drives to the heart of the question: how to run a program as fast as possible.

So, if your Linux system meets the requirements above, then you can execute code from within memory by:

  1. Loading the code into memory somewhere. Malicious actors will have already side-loaded the desired code into memory as part of the initial drop, but if you wanted to do it along the lines of inode, you could do find / -inum 242 -exec cat {} \;
  2. Invoking the userland exec mechanism, setting its entry point to the address of memory where you stored your program from step 1
  3. Profit

The kernel, filesystem, and shell have all been tuned to make the lookup and execution of programs a negligible fraction of the total overhead necessary to do work. Loading a program in memory and executing it from there is not really in the domain of the average use case, so unless doing this for fun I'd say you'd want to benchmark the performance before investing time in trying.

Better address the memory-loading aspect of userland exec and call out find -exec by inode as an obvious answer.
Source Link
bishop
  • 3.2k
  • 2
  • 18
  • 31

Yes, it is possiblepossible to execexecute a file by its inode. The method is fiddly:

find / -inum 242 -exec {} \;

Performance motivated the question, inefficientthough, and the above is not guaranteed to work in all environments. Thusperformant: under the hood, if your motivationthe inode number is efficiencyresolved to a path, this method isn't desirable. But if your motivationand the path is malicious,given to the calculus changeskernel to execute. But why?

Before discussing execution by inode, let's talk about how the kernel does path-based execution. The kernel exposes the exec family of functions (execl, execvp, etc), which all wrap the kernel function execve. That function replaces the current process image with a new process image, one that's been bootstrapped by reading the contents fromfrom a given file path. So every way the kernel gives to execute a program requires it be given fileby path. By using the file path as the entry point, we get all the access control benefits associated with file paths and, for this reason, there is no otherthe "by path" API is the only one in Linux for executing a program.

HoweverSince performance motivated the question, there exists a fiddly and not guaranteed to work in all environments mechanism, but allows you to invoke a program from within memory. Since anything in memory is necessary faster than anything on disk, this drives to the heart of the question.

In early 2002 a (famous) hacker known as grugq introduced the concept of userland exec. This is not a shell's exec function: it's an emulation of every step the kernel's execve function performs, just written in userland. This is ideal for hackers who want to hide their activity because it allows the execution of a program outside the usual access control mechanism of execve.

The implementation for this mechanism is not efficient -- and it need not be for the use case it solves. The mechanismmethod requires numerous helpers that can clean the address space, load the dynamic linker if needed, initialize the stack and so on. The mechanism also requires the desired code be loaded in certain kinds of memory.

So, finally, if your Linux system meets the requirements above, then the two things you need to do are:

  1. Load the inodecode into memory somewhere. HintMalicious actors will have already side-loaded the desired code into memory as part of the initial drop, but if you wanted to do it along the lines of inode, you could do find / -inodeinum 242 -exec cat {} \;
  2. Invoke the userland exec mechanism, setting its entry point to the address of memory where you stored your program from step 1
  3. Profit

Yes, it is possible to exec a file by inode. The method is fiddly, inefficient, and not guaranteed to work in all environments. Thus, if your motivation is efficiency, this method isn't desirable. But if your motivation is malicious, the calculus changes.

Before discussing execution by inode, let's talk about how the kernel does path-based execution. The exec family of functions (execl, execvp, etc) all wrap the kernel function execve. That function replaces the current process image with a new process image, one that's been bootstrapped by reading the contents from the given file. By using the file path as the entry point, we get all the access control benefits associated with file paths and, for this reason, there is no other API in Linux for executing a program.

However, in early 2002 a (famous) hacker known as grugq introduced the concept of userland exec. This is not a shell's exec function: it's an emulation of every step the kernel's execve function performs, just written in userland. This is ideal for hackers who want to hide their activity because it allows the execution of a program outside the usual access control mechanism of execve.

The implementation for this mechanism is not efficient -- and it need not be for the use case it solves. The mechanism requires numerous helpers that can clean the address space, load the dynamic linker if needed, initialize the stack and so on. The mechanism also requires the desired code be loaded in certain kinds of memory.

So, finally, if your Linux system meets the requirements above, then the two things you need to do are:

  1. Load the inode into memory somewhere. Hint, find / -inode 242 -exec cat {} \;
  2. Invoke the userland exec mechanism, setting its entry point to the address of memory where you stored your program from step 1
  3. Profit

Yes, it is possible to execute a file by its inode:

find / -inum 242 -exec {} \;

Performance motivated the question, though, and the above is not performant: under the hood, the inode number is resolved to a path, and the path is given to the kernel to execute. But why?

The kernel exposes the exec family of functions (execl, execvp, etc), which all wrap the kernel function execve. That function replaces the current process image with a new process image, one that's been bootstrapped by reading the contents from a given file path. So every way the kernel gives to execute a program requires it be given by path. By using the file path as the entry point, we get all the access control benefits associated with file paths and, for this reason, the "by path" API is the only one in Linux for executing a program.

Since performance motivated the question, there exists a fiddly and not guaranteed to work in all environments mechanism, but allows you to invoke a program from within memory. Since anything in memory is necessary faster than anything on disk, this drives to the heart of the question.

In early 2002 a (famous) hacker known as grugq introduced the concept of userland exec. This is not a shell's exec function: it's an emulation of every step the kernel's execve function performs, just written in userland. This is ideal for hackers who want to hide their activity because it allows the execution of a program outside the usual access control mechanism of execve.

The implementation for this method requires numerous helpers that can clean the address space, load the dynamic linker if needed, initialize the stack and so on. The mechanism also requires the desired code be loaded in certain kinds of memory.

So, finally, if your Linux system meets the requirements above, then the things you need to do are:

  1. Load the code into memory somewhere. Malicious actors will have already side-loaded the desired code into memory as part of the initial drop, but if you wanted to do it along the lines of inode, you could do find / -inum 242 -exec cat {} \;
  2. Invoke the userland exec mechanism, setting its entry point to the address of memory where you stored your program from step 1
  3. Profit
Source Link
bishop
  • 3.2k
  • 2
  • 18
  • 31
Loading