Articles tagged #rust

Thumbnail for {{ page.title }}

The simplest shared library

In our last article, we managed to load and execute a PIE (position-independent executable) compiled from the following code:

; in `samples/hello-pie.asm` global _start section .text _start: mov rdi, 1 ; stdout fd lea rsi, [rel msg] mov rdx, 9 ; 8 chars + newline mov rax, 1 ; write syscall syscall xor rdi, rdi ; return code 0 mov rax, 60 ; exit syscall syscall section .data msg: db "hi there", 10
Thumbnail for {{ page.title }}

ELF relocations

The last article, Position-independent code, was a mess. But who could blame us? We looked at the world, and found it to be a chaotic and seemingly nonsensical place. So, in order to blend in, we had to let go of a little bit of sanity.

The time has come to reclaim it.

Short of faulty memory sticks, memory locations don’t magically turn from 0x0 into valid addresses. Someone is doing the turning, and we’re going to find out who, if it takes the rest of the series.

Thumbnail for {{ page.title }}

Position-independent code

In the last article, we found where code was hiding in our samples/hello executable, by disassembling the whole file and then looking for syscalls.

Later on, we learned how to inspect which memory ranges are mapped for a given PID (process identifier). We saw that memory areas weren’t all equal: they can be readable, writable, and/or executable.

Thumbnail for {{ page.title }}

Running an executable without exec

In part 1, we’ve looked at three executables:

  • sample, an assembly program that prints “hi there” using the write system call.
  • entry_point, a C program that prints the address of main using printf
  • The /bin/true executable, probably also a C program (because it’s part of GNU coreutils), and which just exits with code 0.

We noticed that when running entry_point through GDB, it always printed the same address. But when we ran it directly, it printed a different address on every run.

Thumbnail for {{ page.title }}

What's in a Linux executable?

Executables have been fascinating to me ever since I discovered, as a kid, that they were just files. If you renamed a .exe to something else, you could open it in notepad! And if you renamed something else to a .exe, you’d get a neat error dialog.

Clearly, something was different about these files. Seen from notepad, they were mostly gibberish, but there had to be order in that chaos. 12-year-old me knew that, although he didn’t quite know how or where to dig to make sense of it all.

Thumbnail for {{ page.title }}

Crafting ICMP-bearing IPv4 packets with the help of bitvec

So. Serializing IPv4 packets. Easy? Well, not exactly.

IPv4 was annoying to parse, because we had 3-bit integers, and 13-bit integers, and who knows what else. Serializing it is going to be exactly the same.

Right now, we don’t have a way to serialize that.

Let’s take the version and ihl fields, both of which are supposed to take 4 bits, together making a byte. We could serialize them like this:

Thumbnail for {{ page.title }}

Crafting ARP packets to find a remote host's MAC address

Alright. ALRIGHT. I know, we’re all excited, but let’s think about what we’re doing again.

So we’ve managed to look at real network traffic and parse it completely. We’ve also taken some ICMP packets, parsed them, and then serialized them right back and we got the exact same result.

So I know what you’re thinking - let’s just move our way down the stack again - stuff that ICMP packet in an IP packet, then in an Ethernet frame, and then serialize the whole thing.

Thumbnail for {{ page.title }}

Parsing and serializing ICMP packets with cookie-factory.

In the last part, we’ve finally parsed some IPv4 packets. We even found a way to filter only IPv4 packets that contain ICMP packets.

There’s one thing we haven’t done though, and that’s verify their checksum. Folks could be sending us invalid IPv4 packets and we’d be parsing them like a fool!

This series is getting quite long, so let’s jump right into it.

Go back to the homepage.