Skip to content

Add APE interpreter #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lemaitre opened this issue Sep 2, 2021 · 5 comments
Closed

Add APE interpreter #263

lemaitre opened this issue Sep 2, 2021 · 5 comments

Comments

@lemaitre
Copy link
Contributor

lemaitre commented Sep 2, 2021

There is interest in keeping the the binary unaltered after execution, in order to keep it portable, and thus shareable. see: #82 #85 #146 #236

I have two ideas that would go in that direction.

Repatch

Currently, the APE is a shell script that patches itself in order to be a valid ELF.

What could be done is at the start of the ELF binary, patch back the file to be a valid APE again. Then continue with normal execution.

It would still require write permission to the APE, but at least, it would still be portable afterwards.

Loader

Another way would be to not patch the APE at all, and create a loader that would mmap the APE in memory, and jump at the starting address.
The loader would be a tiny ELF embedded in the APE, that would be copied into a temp file, and that temp ELF started passing the current APE as a parameter to the loader.
As the loader would be tiny, I think it would be an acceptable solution to copy it every time an APE is executed.

This would solve the write permission issue, but would require to get a temporary folder where a file could be both created and executed. It might be tricky to do in a portable way.

@pkulchenko
Copy link
Collaborator

@lemaitre, isn't this what's already available in ape-no-modify-self.o according to #82 (comment)?

@jart jart changed the title Ideas to make binaries still portable after execution Add APE interpreter Sep 4, 2021
jart added a commit that referenced this issue Sep 4, 2021
@jart
Copy link
Owner

jart commented Sep 4, 2021

Yes we have ape-no-modify-self.o which enables the non-modification use case, at the cost of performance, with caveats. See ape.S for documentation on the matter, plus what's written in the issues.

I don't think we've discussed the idea of creating a loader payload yet. So I've added one to the examples folder. It's relatively straightforward to load an APE executable into memory and execute it. I hope that examples/loader.c will add some clarity. You can run it as follows:

m=tiny
make -j8 MODE=$m o/$m/examples
o/$m/examples/loader.elf o/$m/examples/printargs.com

@jart jart closed this as completed Sep 4, 2021
@jart
Copy link
Owner

jart commented Sep 4, 2021

Note: We should also probably write a formal specification for the APE format and then upstream patches to the Linux and BSD kernels so they can run it without the script step.

@lemaitre
Copy link
Contributor Author

lemaitre commented Sep 4, 2021

@lemaitre, isn't this what's already available in ape-no-modify-self.o according to #82 (comment)?

It is the same goal, but what I propose is different. As far as I understand, the solution in #82 is to copy the whole APE in a TMP dir, and have this copy patched. The problem here is that if the APE is large, then the copy will also be large.

My loader proposal would be to copy a tiny ELF that would then load the APE without the need to modify it. The APE bash script would then just need to exec the loader with itself. The APE loader would be small, so copying it is not a big deal. It could be shared among several APEs or even provided by the OS (as a lighter alternative to patch the kernel).

My other repatch proposal is different and does not need to create any file, but still requires writing permission to the APE. After the APE has been patch to ELF and started again, it would patch itself back to being a proper APE.

Both my solutions are fast, even if the APE is large. While the current solution requires to copy the complete APE, which is a big overhead if the file is large.

@jart
Copy link
Owner

jart commented Sep 4, 2021

I've implemented your proposal, for Linux, in the aforementioned commit. Although it hasn't been incorporated into ape.S.

I would support this becoming the new solution to ape-no-modify-self if you're willing to take it the rest of the way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants