Live data from Hacker News

In-Memory-Only ELF Execution Without Tmpfs

magisterquis.github.io

11–20 of 24 posts

Re: In-Memory-Only ELF Execution Without Tmpfs

#11

Oh yeah, I've once discovered this method myself. With execveat() one can even avoid going through procfs. It doesn't work worth shbang-based scripts, though; that just returns ENOENT. Makes sense, I suppose.

Would you be willing to share how you did that (avoiding procfs too)?

Re: In-Memory-Only ELF Execution Without Tmpfs

#13
post #5

There are other ways to do this that don't involve tmpfs or write() - see https://github.com/dimkr/papaw and https://github.com/dimkr/Mirai-Source-Code

But the readme says:

The payload executable is extracted to a temporary file. When running as root, this is done by mounting a tmpfs file system and lazily unmounting it before the extraction.

Re: In-Memory-Only ELF Execution Without Tmpfs

#14
post #3

And when would you want to do that ? Really curious as I fail to see a usecase where the same goal could not be achieve otherwise. But there must be some otherwise the API would not have been introduced i guess.

It lets you execute files even with no writeable filesystem , which could be useful exploiting a locked down system. It is also an argument that locking down programs with no writeable fs is not sufficient for security.

The memfd api has lots of other uses, the fact you can exec is just a byproduct.

Re: In-Memory-Only ELF Execution Without Tmpfs

#16
Given that Linux now has both file descriptors, and process memory-page ranges, pointing to anonymous allocated memory regions, are they interchangeable?

What I mean is:

- to go from a memfd to anonymous memory, you can call mmap(2) on the fd

- to go from anonymous memory to a memfd, you...?

Re: In-Memory-Only ELF Execution Without Tmpfs

#17
post #16

Given that Linux now has both file descriptors, and process memory-page ranges, pointing to anonymous allocated memory regions, are they interchangeable? What I mean is: - to go from a memfd to anonymous memory, you can call mmap(2) on the fd - to go from anonymous memory to a memfd, you...?

Semantically this should do the job: anonymous memory -> vmsplice(gift) -> pipe -> splice(move) -> memfd. Then remap the pages from memfd to the original address ranges so you're allowed to use them again. But I don't know whether this is supported on memfds. And of course it's not atomic.

Re: In-Memory-Only ELF Execution Without Tmpfs

#18
post #13
post #5

There are other ways to do this that don't involve tmpfs or write() - see https://github.com/dimkr/papaw and https://github.com/dimkr/Mirai-Source-Code

But the readme says: The payload executable is extracted to a temporary file. When running as root, this is done by mounting a tmpfs file system and lazily unmounting it before the extraction.

When not running as root, it doesn't use a tmpfs. Also, papaw replaces /proc/self/exe with an empty file. And it has some basic anti-debugging, like locking of the payload to RAM so it cannot be recovered by reading it from a swap partition.

Re: In-Memory-Only ELF Execution Without Tmpfs

#19
post #8
post #6

Earlier quoted context omitted.

But a tmpfs (the usual way to do this) isn't persisted to a disk

It can be; swap and suspend-to-disk / hibernation can cause tmpfs to be written. I wonder if there's a way to execute from mlock'd or madvised memory. I can imagine this be particularly useful, if you wanted to prevent your injected program (malware? valuable IP?) from being written to disk or appearing in a core dump.

True, but those caveats apply to OP's technique too. What I am saying is that there is no specific behavior of a tmpfs which causes things in it to be necessarily persisted to disk like the parent was suggesting. It works just like any other anonymous memory does.

Re: In-Memory-Only ELF Execution Without Tmpfs

#20

A bit off-topic, but their perl code is buggy. fork() returns undef on error, not -1. And you can use '$FH->autoflush(1)' instead of the eye-watering 'select((select($FH), $|=1)[0])'

I was going to say that you need to use the IO::Handle module to be able to use the autoflush method, but apparently this no longer necessary with modern Perl.

From https://metacpan.org/pod/perl5120delta#Other-potentially-inc... :

> Filehandles are now always blessed into IO::File.

> The previous behaviour was to bless Filehandles into FileHandle (an empty proxy class) if it was loaded into memory and otherwise to bless them into IO::Handle.

Post reply on HN