Articles tagged #assembly

What makes a trampoline bounce

I've been building up to this article for a few months now!

This is peak "the kind of content I started writing seriously for". In a time where you can do a lot of useful things in life just by swiping on a mobile device, I think it's even more important to understand what's going on inside these devices.

And not just for experts, for whom it's their day job, but for everyone who's curious enough. This is my attempt at making all of that a little less scary.

Fine, we'll relocate our own binary!

Welcome back to the eighteenth and final part of "Making our own executable packer".

In the last article, we had a lot of fun. We already had a "packer" executable, minipak, which joined together stage1 (a launcher), and a compressed version of whichever executable we wanted to pack.

What we added, was a whole bunch of abstractions to parse ELF headers using , which we used from to be able to launch the guest executable from memory, instead of writing it to a file and using on it.

Running a self-relocatable ELF from memory

Welcome back!

In the last article, we did foundational work on minipak, our ELF packer.

It is now able to receive command-line arguments, environment variables, and auxiliary vectors. It can parse those command-line arguments into a set of options. It can make an ELF file smaller using the LZ4 compression algorithm, and pack it together with stage1, our launcher.

Everything but ELF

And we're back!

In the last article, we thanked our old code and bade it adieu, for it did not spark joy. And then we made a new, solid foundation, on which we planned to actually make an executable packer.

As part of this endeavor, we've made a crate called encore, which only depends on libcore, and provides some of the things libstd would give us, but which we cannot have, because we do not want to rely on a libc.

Between libcore and libstd

You're still here! Fantastic.

I have good news, and bad news. The good news is, we're actually going to make an executable packer now!

Bear

Hurray!

I know right? No lie, we're actually really going to start working on the final product from this point onwards.

Bear

What uhhh what about the previous fourteen parts?

Ah, yes, the previous fourteen parts. Well, we had fun, didn't we? And we learned a lot about ELF, how it's basically a database format that different tools look at in different ways, how it's mapped in memory (more or less), what we need to set up before starting up another executable, all that good stuff.

In the bowels of glibc

Good morning, and welcome back to "how many executables can we run with our custom dynamic loader before things get really out of control".

In Part 13, we "implemented" thread-local storage. I'm using scare quotes because, well, we spent most of the article blabbering about Addressing Memory Through The Ages, And Other Fun Tidbits.

we
Making our own executable packer

In this series, we'll attempt to understand how Linux executables are organized, how they are executed, and how to make a program that takes an executable fresh off the linker and compresses it - just because we can.

Running glibc applications

In the last article, we implemented thread-local storage.

Well, some of it. We didn't actually bother supporting any kind of threading, so, if we try to load and execute a multithreaded program

Shell session
$ cargo b -q && gdb --args ./target/debug/elk run /bin/ls
(gdb) break jmp
Breakpoint 1 at 0x47e02: file src/process.rs, line 819.
(gdb) r
Starting program: /home/amos/ftl/elk/target/debug/elk run /bin/ls
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Loading "/usr/bin/ls"
Loading "/usr/lib/libcap.so.2.33"
Loading "/usr/lib/libc-2.31.so"
Loading "/usr/lib/ld-2.31.so"

Breakpoint 1, elk::process::jmp (
    entry_point=0x7ffff7faab20 "\363\017\036\372\061\355I\211\321^H\211\342H\203\344\360PTL\215\005f\030\001\000",
    stack_contents=0x5555557150a0, qword_count=94) at src/process.rs:819
819         asm!(
(gdb) autosym
add symbol table from file "/home/amos/ftl/elk/target/debug/elk" at
        .text_addr = 0x555555565160
add symbol table from file "/usr/lib/ld-2.31.so" at
        .text_addr = 0x7ffff7a94100
add symbol table from file "/usr/lib/libc-2.31.so" at
        .text_addr = 0x7ffff7ba6630
add symbol table from file "/usr/lib/libgcc_s.so.1" at
        .text_addr = 0x7ffff7d8d020
add symbol table from file "/usr/lib/libpthread-2.31.so" at
        .text_addr = 0x7ffff7dabad0
add symbol table from file "/usr/lib/libdl-2.31.so" at
        .text_addr = 0x7ffff7dc7210
add symbol table from file "/usr/lib/libc-2.31.so" at
        .text_addr = 0x7ffff7df0630
add symbol table from file "/usr/lib/libcap.so.2.33" at
        .text_addr = 0x7ffff7f9e020
add symbol table from file "/usr/bin/ls" at
        .text_addr = 0x7ffff7fa9040
add symbol table from file "/usr/lib/ld-2.31.so" at
        .text_addr = 0x7ffff7fd3100
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()

Go back to the homepage.