Congratulations.
By now, you have gained a solid understanding of how the binary compilation process works and have
explored the inner workings of binaries.
You have even delved into the realm of static disassembly using objdump, and if you've been following
along, you may have your very own shiny new binaries sitting on your hard drive.
Now it's time to dive into the fascinating journey of loading and executing a binary.
A crucial topic that will pave the way for exploring dynamic analysis concepts in upcoming sections.
While the precise details may vary depending on the platforms and binary format, the process of loading
and executing a binary typically involves a series of fundamental steps.
And here I draw some diagram.
Here.
In this diagram we are providing a glimpse of.
Binaries into how an elf binary such as the one we just compiled in previous lecture, is represented
in memory on a Linux based platform.
On a high level, the process of loading a binary on Windows follows a similar pattern.
So the process of loading a binary is so intricate and requires substantial effort from the operating
system.
And it's important to note that the binaries representation in memory does not necessarily mirror its
own disk representation.
For example, sections of zero initialized.
Zero initialized data within the on disk binary may have compressed to conserve disk space.
So however, when loaded into memory, these sections expand to contain the actual zero values.
So furthermore, certain portions of the on disc binary may be recorded in memory or not loaded into
memory at all.
So as the intricacies of on disk versus in memory, binary representations are closely tied to a specific
binary formats.
We will explore this topic in greater detail in the next sections.
For now, let's focus on the high level overview of the loading process.
So when you decide to run binary, the operating system initiates the setup of a new process dedicated
to running the program, complete with its own virtual address space.
Subsequently, the operating system maps an interpreter into the virtual memory of the process.
This interpreter, a user space program possesses the knowledge and capability to load the binary and
perform the necessary relocations on Linux system.
The interpreter is typically shared library known as a Linux, so here or lib one lib 2.0.
Conversely, on Windows, the interpreter functionality is integrated into the ntdll.dll so once the
interpreter is loaded, the kernel hands over control to it and the interpreter begins its work with
the userspace environment.
So the role of the interpreter is crucial in preparing the binary for execution.
It carries out a series of tasks such as resolving symbol references, setting up the program's initial
memory layout and performing necessary relocations.
By delegating these responsibilities to the interpreter, the operating system can ensure a consistent
and reliable execution environment for binaries across various platforms.
Understanding the loading process is essential as it forms the foundation for dynamic analysis techniques
that we will explore in next sections.
Stay tuned for further exciting insights into dynamic analysis of binaries here.
So.
Here.
What are we going to do is we will first open our Linux machine here.
Let me change the screen here.
Holly here.
It's clear that console and now.
Linux Elf binaries come with a special section called the int int ARP that specifies the path to the
interpreter that is to be used to load the binary.
Now we will see that with red elf with P here dot interp a of my app dot.
All here.
Pay that out because.
And that's it.
And here.
As you can see with Rudolph, we are saying this the interpreter part of the interpreter.
And as mentioned here, the interpreter loads the binary into its virtual address space.
The space in which the interpreter is loaded, and it then parses the binary to find out.
Among other things, which dynamic libraries the binary uses.
So the interpreter maps these into virtual address space using map or an equivalent function, and then
performs any necessary last minute relocations in the binary code sections.
So.
So as I said this.
Does any last minute relocations in the binary code sections to fill in the correct addresses for references
to the dynamic libraries.
In reality, the process of resolving resolving references to functions in dynamic libraries is often
deferred until later.
So in other words, instead of resolving these references immediately at load time, the interpreter
resolves references only when they are invoking for the first time.
So this is known as lazy binding, which I will explain in more detail in next sections.
And after relocation is complete, the interpreter looks up the entry point of the binary and transfers
control to it, beginning normal execution of the binary.
Now that you are familiar with the general anatomy of a life cycle of a binary, it's time to dive into
the details of specific binary format.
And we will start with the widespread Elf format, which is the subject of the next sections of our
course.
And I'm waiting you in next lecture.