<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ddupard</title>
    <description>The latest articles on DEV Community by ddupard (@ddupard).</description>
    <link>https://dev.to/ddupard</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3949744%2Fab1a1cf3-7a46-4fa9-92d1-8ac9855809d3.png</url>
      <title>DEV Community: ddupard</title>
      <link>https://dev.to/ddupard</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ddupard"/>
    <language>en</language>
    <item>
      <title>X86_64 From Source Code to Binary: What Does GCC Actually Do? part 3</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Thu, 23 Jul 2026 20:23:00 +0000</pubDate>
      <link>https://dev.to/ddupard/x8664-from-source-code-to-binary-what-does-gcc-actually-do-part-3-3ca8</link>
      <guid>https://dev.to/ddupard/x8664-from-source-code-to-binary-what-does-gcc-actually-do-part-3-3ca8</guid>
      <description>&lt;p&gt;Having explained how GCC uses the System V AMD64 ABI convention for passing parameters , how GCC uses the stack to manage local variables and how GCC returns values from a function, it's time to explain some of the options GCC has to prevent the buffer overflow attack &lt;/p&gt;

&lt;p&gt;To illustrate the buffer overflow protection mechanism, I will use the following program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;arpa/inet.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define PORT 8080
#define BUFFER_SIZE 64
&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test1"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test2&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;strcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;buffer1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;buffer2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



&lt;span class="cm"&gt;/**
 * handle_client: Processes incoming connections.
 * This function contains a deliberate stack-based buffer overflow 
 * vulnerability for educational purposes.
 */&lt;/span&gt;


&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BUFFER_SIZE&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Read the incoming request from the client&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bytes_received&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes_received&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bytes_received&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="cm"&gt;/* * THE VULNERABILITY: 
         * strcpy() does not perform bounds checking. If 'request' 
         * exceeds 64 bytes, it will overflow 'buffer' and overwrite 
         * critical data on the stack, including the saved return address.
         */&lt;/span&gt;
        &lt;span class="n"&gt;strcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;test2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;



    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;server_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;sockaddr_in&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;htons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;INADDR_ANY&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Bind the socket to the port and start listening&lt;/span&gt;
    &lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server listening on port %d...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;client_socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This program will be compiled with GCC and the binary generated will be disassembled by objdump using the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server.objdump_clean"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fno-stack-protector&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt;  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/buffer_overflow/C/server.c"&lt;/span&gt;
    objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server.objdump"&lt;/span&gt;
    python3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ATP&lt;/span&gt;&lt;span class="s2"&gt;/clean_objdump.py"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server.objdump"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server.objdump_clean"&lt;/span&gt;
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sp.objdump_clean"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fstack-protector&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt;  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sp"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/buffer_overflow/C/server.c"&lt;/span&gt;
    objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sp"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sp.objdump"&lt;/span&gt;
    python3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ATP&lt;/span&gt;&lt;span class="s2"&gt;/clean_objdump.py"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sp.objdump"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sp.objdump_clean"&lt;/span&gt;
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sps.objdump_clean"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fstack-protector-strong&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt;  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sps"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/buffer_overflow/C/server.c"&lt;/span&gt;
    objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sps"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sps.objdump"&lt;/span&gt;
    python3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ATP&lt;/span&gt;&lt;span class="s2"&gt;/clean_objdump.py"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sps.objdump"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_sps.objdump_clean"&lt;/span&gt;
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_spa.objdump_clean"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fstack-protector-all&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt;  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_spa"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/buffer_overflow/C/server.c"&lt;/span&gt;
    objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_spa"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_spa.objdump"&lt;/span&gt;
    python3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ATP&lt;/span&gt;&lt;span class="s2"&gt;/clean_objdump.py"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_spa.objdump"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_spa.objdump_clean"&lt;/span&gt;
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_default.objdump_clean"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt;  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_default"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/buffer_overflow/C/server.c"&lt;/span&gt;
    objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_default"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_default.objdump"&lt;/span&gt;
    python3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ATP&lt;/span&gt;&lt;span class="s2"&gt;/clean_objdump.py"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_default.objdump"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_3/server_default.objdump_clean"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The option ( -M intel ) forces the intel convention in the disasssembling process. I prefer the intel convetion over the ATT convention. &lt;/p&gt;

&lt;h3&gt;
  
  
  1.  The stack based buffer overflow mechanism
&lt;/h3&gt;

&lt;p&gt;A "buffer overflow" occurs when a program writes more data to a buffer than its allocated capacity, overwriting adjacent memory and resulting in the corruption of adjacent memory —most notably the saved return address on the stack. It can happen when using functions like strcpy, memcpy, ..&lt;br&gt;
Buffers can be allocated on stack so we use the term stack based buffer overflow or on heap and we use the term Heap buffer overflow.&lt;/p&gt;

&lt;p&gt;For example in our C program, we copy the information found in request (256 bytes) in a buffer containing only 64 bytes using the following line&lt;br&gt;
strcpy(buffer, request);&lt;br&gt;
This results to a corruption of the stack which normally contains the return address of the function, so an attacker by modifying the return address can change the execution flow of the program and execute an arbitrary code.&lt;br&gt;&lt;br&gt;
Since this buffer is allocated on stack using a local variable, we are creating a stack based buffer overflow.&lt;/p&gt;

&lt;p&gt;GCC default options partially protect programs from it but we will see that some stack based buffer overflows are still found each year even in programs where we do not expect to find them.&lt;/p&gt;

&lt;p&gt;but let's start with GCC options&lt;/p&gt;
&lt;h3&gt;
  
  
  2.  -fno-stack-protector
&lt;/h3&gt;

&lt;p&gt;This option removes the default GCC mechanism of protecting programs from stack based buffer overflows. This is only useful to study the stack based buffer overflow mechanism and I don't see any other reason to have this option set when compiling a program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401256 &amp;lt;test1&amp;gt;:
401256:  endbr64
40125a:  push   rbp
40125b:  mov    rbp,rsp
40125e:  sub    rsp,0x10
401262:  lea    rax,[rip+0xd9f]        # 402008 &amp;lt;_IO_stdin_used+0x8&amp;gt;
401269:  mov    QWORD PTR [rbp-0x8],rax
40126d:  lea    rax,[rip+0xffffffffffffffe2]        # 401256 &amp;lt;test1&amp;gt;
401274:  mov    rdi,rax
401277:  call   4010f0 &amp;lt;puts@plt&amp;gt;
40127c:  nop
40127d:  leave
40127e:  ret

000000000040127f &amp;lt;test2&amp;gt;:
40127f:  endbr64
401283:  push   rbp
401284:  mov    rbp,rsp
401287:  sub    rsp,0x10
40128b:  lea    rax,[rip+0xd7c]        # 40200e &amp;lt;_IO_stdin_used+0xe&amp;gt;
401292:  mov    BYTE PTR [rbp-0x1],al
401295:  lea    rax,[rip+0xd78]        # 402014 &amp;lt;_IO_stdin_used+0x14&amp;gt;
40129c:  mov    BYTE PTR [rbp-0x2],al
40129f:  movsx  edx,BYTE PTR [rbp-0x2]
4012a3:  movsx  eax,BYTE PTR [rbp-0x1]
4012a7:  mov    esi,eax
4012a9:  lea    rax,[rip+0xd66]        # 402016 &amp;lt;_IO_stdin_used+0x16&amp;gt;
4012b0:  mov    rdi,rax
4012b3:  mov    eax,0x0
4012b8:  call   401110 &amp;lt;printf@plt&amp;gt;
4012bd:  nop
4012be:  leave
4012bf:  ret

00000000004012c0 &amp;lt;handle_client&amp;gt;:
4012c0:  endbr64
4012c4:  push   rbp
4012c5:  mov    rbp,rsp
4012c8:  sub    rsp,0x160
4012cf:  mov    DWORD PTR [rbp-0x154],edi
4012d5:  lea    rsi,[rbp-0x150]
4012dc:  mov    eax,DWORD PTR [rbp-0x154]
4012e2:  mov    ecx,0x0
4012e7:  mov    edx,0xff
4012ec:  mov    edi,eax
4012ee:  call   4010d0 &amp;lt;recv@plt&amp;gt;
4012f3:  mov    DWORD PTR [rbp-0x4],eax
4012f6:  cmp    DWORD PTR [rbp-0x4],0x0
4012fa:  jle    40134e &amp;lt;handle_client+0x8e&amp;gt;
4012fc:  mov    eax,DWORD PTR [rbp-0x4]
4012ff:  cdqe
401301:  mov    BYTE PTR [rbp+rax*1-0x150],0x0
401309:  lea    rdx,[rbp-0x150]
401310:  lea    rax,[rbp-0x50]
401314:  mov    rsi,rdx
401317:  mov    rdi,rax
40131a:  call   4010e0 &amp;lt;strcpy@plt&amp;gt;
40131f:  lea    rax,[rbp-0x50]
401323:  mov    rsi,rax
401326:  lea    rax,[rip+0xcee]        # 40201b &amp;lt;_IO_stdin_used+0x1b&amp;gt;
40132d:  mov    rdi,rax
401330:  mov    eax,0x0
401335:  call   401110 &amp;lt;printf@plt&amp;gt;
40133a:  mov    eax,0x0
40133f:  call   401256 &amp;lt;test1&amp;gt;
401344:  mov    eax,0x0
401349:  call   40127f &amp;lt;test2&amp;gt;
40134e:  mov    eax,DWORD PTR [rbp-0x154]
401354:  mov    edi,eax
401356:  call   401120 &amp;lt;close@plt&amp;gt;
40135b:  nop
40135c:  leave
40135d:  ret

000000000040135e &amp;lt;main&amp;gt;:
40135e:  endbr64
401362:  push   rbp
401363:  mov    rbp,rsp
401366:  sub    rsp,0x20
40136a:  mov    edx,0x0
40136f:  mov    esi,0x1
401374:  mov    edi,0x2
401379:  call   401160 &amp;lt;socket@plt&amp;gt;
40137e:  mov    DWORD PTR [rbp-0x4],eax
401381:  mov    QWORD PTR [rbp-0x20],0x0
401389:  mov    QWORD PTR [rbp-0x18],0x0
401391:  mov    WORD PTR [rbp-0x20],0x2
401397:  mov    edi,0x1f90
40139c:  call   401100 &amp;lt;htons@plt&amp;gt;
4013a1:  mov    WORD PTR [rbp-0x1e],ax
4013a5:  lea    rcx,[rbp-0x20]
4013a9:  mov    eax,DWORD PTR [rbp-0x4]
4013ac:  mov    edx,0x10
4013b1:  mov    rsi,rcx
4013b4:  mov    edi,eax
4013b6:  call   401140 &amp;lt;bind@plt&amp;gt;
4013bb:  mov    eax,DWORD PTR [rbp-0x4]
4013be:  mov    esi,0x3
4013c3:  mov    edi,eax
4013c5:  call   401130 &amp;lt;listen@plt&amp;gt;
4013ca:  mov    esi,0x1f90
4013cf:  lea    rax,[rip+0xc5a]        # 402030 &amp;lt;_IO_stdin_used+0x30&amp;gt;
4013d6:  mov    rdi,rax
4013d9:  mov    eax,0x0
4013de:  call   401110 &amp;lt;printf@plt&amp;gt;
4013e3:  mov    eax,DWORD PTR [rbp-0x4]
4013e6:  mov    edx,0x0
4013eb:  mov    esi,0x0
4013f0:  mov    edi,eax
4013f2:  call   401150 &amp;lt;accept@plt&amp;gt;
4013f7:  mov    DWORD PTR [rbp-0x8],eax
4013fa:  mov    eax,DWORD PTR [rbp-0x8]
4013fd:  mov    edi,eax
4013ff:  call   4012c0 &amp;lt;handle_client&amp;gt;
401404:  nop
401405:  jmp    4013e3 &amp;lt;main+0x85&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;let notice several things&lt;br&gt;
First the size of the local memory allocated on the stack (0x160) for the handle_client function&lt;br&gt;
4012c8:  sub    rsp,0x160&lt;/p&gt;
&lt;h3&gt;
  
  
  3. -fstack-protector
&lt;/h3&gt;

&lt;p&gt;Let's see what the man page says about the option &lt;/p&gt;

&lt;p&gt;-fstack-protector&lt;br&gt;
      Emit extra code to check for buffer overflows, such as stack&lt;br&gt;
      smashing attacks.  This is done by adding a guard variable to&lt;br&gt;
      functions with vulnerable objects.  This includes functions&lt;br&gt;
      that call "alloca", and functions with buffers larger than 8&lt;br&gt;
      bytes.  The guards are initialized when a function is entered&lt;br&gt;
      and then checked when the function exits.  If a guard check&lt;br&gt;
      fails, an error message is printed and the program exits&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401276 &amp;lt;test1&amp;gt;:
401276:  endbr64
40127a:  push   rbp
40127b:  mov    rbp,rsp
40127e:  sub    rsp,0x10
401282:  lea    rax,[rip+0xd7f]        # 402008 &amp;lt;_IO_stdin_used+0x8&amp;gt;
401289:  mov    QWORD PTR [rbp-0x8],rax
40128d:  lea    rax,[rip+0xffffffffffffffe2]        # 401276 &amp;lt;test1&amp;gt;
401294:  mov    rdi,rax
401297:  call   401100 &amp;lt;puts@plt&amp;gt;
40129c:  nop
40129d:  leave
40129e:  ret

000000000040129f &amp;lt;test2&amp;gt;:
40129f:  endbr64
4012a3:  push   rbp
4012a4:  mov    rbp,rsp
4012a7:  sub    rsp,0x10
4012ab:  lea    rax,[rip+0xd5c]        # 40200e &amp;lt;_IO_stdin_used+0xe&amp;gt;
4012b2:  mov    BYTE PTR [rbp-0x2],al
4012b5:  lea    rax,[rip+0xd58]        # 402014 &amp;lt;_IO_stdin_used+0x14&amp;gt;
4012bc:  mov    BYTE PTR [rbp-0x1],al
4012bf:  movsx  edx,BYTE PTR [rbp-0x1]
4012c3:  movsx  eax,BYTE PTR [rbp-0x2]
4012c7:  mov    esi,eax
4012c9:  lea    rax,[rip+0xd46]        # 402016 &amp;lt;_IO_stdin_used+0x16&amp;gt;
4012d0:  mov    rdi,rax
4012d3:  mov    eax,0x0
4012d8:  call   401130 &amp;lt;printf@plt&amp;gt;
4012dd:  nop
4012de:  leave
4012df:  ret

00000000004012e0 &amp;lt;handle_client&amp;gt;:
4012e0:  endbr64
4012e4:  push   rbp
4012e5:  mov    rbp,rsp
4012e8:  sub    rsp,0x170
4012ef:  mov    DWORD PTR [rbp-0x164],edi
4012f5:  mov    rax,QWORD PTR fs:0x28
4012fe:  mov    QWORD PTR [rbp-0x8],rax
401302:  xor    eax,eax
401304:  lea    rsi,[rbp-0x110]
40130b:  mov    eax,DWORD PTR [rbp-0x164]
401311:  mov    ecx,0x0
401316:  mov    edx,0xff
40131b:  mov    edi,eax
40131d:  call   4010e0 &amp;lt;recv@plt&amp;gt;
401322:  mov    DWORD PTR [rbp-0x154],eax
401328:  cmp    DWORD PTR [rbp-0x154],0x0
40132f:  jle    40138c &amp;lt;handle_client+0xac&amp;gt;
401331:  mov    eax,DWORD PTR [rbp-0x154]
401337:  cdqe
401339:  mov    BYTE PTR [rbp+rax*1-0x110],0x0
401341:  lea    rdx,[rbp-0x110]
401348:  lea    rax,[rbp-0x150]
40134f:  mov    rsi,rdx
401352:  mov    rdi,rax
401355:  call   4010f0 &amp;lt;strcpy@plt&amp;gt;
40135a:  lea    rax,[rbp-0x150]
401361:  mov    rsi,rax
401364:  lea    rax,[rip+0xcb0]        # 40201b &amp;lt;_IO_stdin_used+0x1b&amp;gt;
40136b:  mov    rdi,rax
40136e:  mov    eax,0x0
401373:  call   401130 &amp;lt;printf@plt&amp;gt;
401378:  mov    eax,0x0
40137d:  call   401276 &amp;lt;test1&amp;gt;
401382:  mov    eax,0x0
401387:  call   40129f &amp;lt;test2&amp;gt;
40138c:  mov    eax,DWORD PTR [rbp-0x164]
401392:  mov    edi,eax
401394:  call   401140 &amp;lt;close@plt&amp;gt;
401399:  nop
40139a:  mov    rax,QWORD PTR [rbp-0x8]
40139e:  sub    rax,QWORD PTR fs:0x28
4013a7:  je     4013ae &amp;lt;handle_client+0xce&amp;gt;
4013a9:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
4013ae:  leave
4013af:  ret

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this assembly , one can see that the option -fstack-protector has modified several things, &lt;/p&gt;

&lt;p&gt;First (step 1) the size of the local memory allocated on the stack (0x170)&lt;br&gt;
4012e8:  sub    rsp,0x170&lt;/p&gt;

&lt;p&gt;Second (step 2) at the begining of the handle_function, right after the local memory allocation, GCC adds the following 3 lines&lt;br&gt;
4012f5:  mov    rax,QWORD PTR fs:0x28&lt;br&gt;
4012fe:  mov    QWORD PTR [rbp-0x8],rax&lt;br&gt;
401302:  xor    eax,eax&lt;/p&gt;

&lt;p&gt;Third (step 3) GCC  adds some lines at the end of the handle_client function&lt;br&gt;
40139a:  mov    rax,QWORD PTR [rbp-0x8]&lt;br&gt;
40139e:  sub    rax,QWORD PTR fs:0x28&lt;br&gt;
4013a7:  je     4013ae &lt;br&gt;
4013a9:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;So how this mechanism works ?&lt;br&gt;
The program at execution is going to add a random list of bytes (called the stack canary, stack cookie ) at the end of the stack allocated. &lt;br&gt;
In order to do that, it has to allocate some more space (step 1) on the stack than when there is no protection.&lt;br&gt;
Then it copies 8 bytes from a specific location ( fs:0x28 see step 2) to the end of the stack ( [rbp-0x8] )&lt;br&gt;&lt;br&gt;
Then at the end of the function, the program checks that the stack canary has not been corrupted else it calls __stack_chk_fail@plt     &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Understanding mov rax, QWORD PTR fs:0x28 &lt;br&gt;
This instruction is used to ensure the integrity of the program's execution.&lt;br&gt;
This instruction copies a value located in a special memory segment ( fs ) into the rax register.&lt;br&gt;
In protected mode, the fs segment register points to a thread-specific memory structure called Thread Local Storage (TLS) or the tcbhead_t (Thread Control Block). The 0x28 offset: This is the specific location where the "Stack Canary" is stored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who generates the value at fs:0x28?&lt;br&gt;
The execution environment, specifically the dynamic linker (/usr/lib64/ld-linux-x86-64.so.2 or /usr/lib32/ld-linux.so.2).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the chain of responsibility:&lt;/p&gt;

&lt;p&gt;a. The role of the Dynamic Linker&lt;br&gt;
When you run a program on Linux, before the main function executes, the kernel loads the binary into memory and then hands control to the dynamic linker. This is the component that sets up the process environment.&lt;/p&gt;

&lt;p&gt;During this initialization phase, the linker generates a random (or pseudo-random) value using a system call, typically getrandom() or by reading /dev/urandom. This value is then copied into the internal tcbhead_t structure associated with the fs segment. This is precisely when fs:0x28 is populated.&lt;/p&gt;

&lt;p&gt;b. Why the linker and not the program?&lt;br&gt;
It is imperative that this value is generated before your program code begins to execute. If the program itself generated the canary, it would need to be protected during that generation, creating a "chicken and egg" problem. By delegating this to the system linker, we ensure that every thread is protected from its very first cycle of execution.&lt;/p&gt;

&lt;p&gt;c. Persistence of the value&lt;br&gt;
Once the linker places this value at fs:0x28, it remains read-only (in theory) for the thread for its entire lifetime.&lt;/p&gt;

&lt;p&gt;Per process: The canary is generally the same for all threads within a single process.&lt;/p&gt;

&lt;p&gt;Per execution: Every time the program starts, the linker generates a new value. This is why even if an attacker discovers the canary for one session, they cannot use it for another; they would have to leak it again.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;why the name stack canary  ?&lt;br&gt;
The name comes from the use of canaries in a mine. In mines they used canaries to alert for gas poisoning. If the canary stops singing, it means that you have to get out before you die from gas poisoning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally&lt;br&gt;
In the example above handle_client is protected but not test1 nor test2 &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  4. fstack-protector-strong
&lt;/h3&gt;

&lt;p&gt;Let's see what the man page says about the option &lt;br&gt;
-fstack-protector-strong&lt;br&gt;
          Like -fstack-protector but includes additional functions to be&lt;br&gt;
          protected --- those that have local array definitions, or have&lt;br&gt;
          references to local frame addresses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401276 &amp;lt;test1&amp;gt;:
401276:  endbr64
40127a:  push   rbp
40127b:  mov    rbp,rsp
40127e:  sub    rsp,0x10
401282:  lea    rax,[rip+0xd7f]        # 402008 &amp;lt;_IO_stdin_used+0x8&amp;gt;
401289:  mov    QWORD PTR [rbp-0x8],rax
40128d:  mov    rax,QWORD PTR [rbp-0x8]
401291:  mov    rdi,rax
401294:  call   401100 &amp;lt;puts@plt&amp;gt;
401299:  nop
40129a:  leave
40129b:  ret

000000000040129c &amp;lt;test2&amp;gt;:
40129c:  endbr64
4012a0:  push   rbp
4012a1:  mov    rbp,rsp
4012a4:  sub    rsp,0x70
4012a8:  mov    rax,QWORD PTR fs:0x28
4012b1:  mov    QWORD PTR [rbp-0x8],rax
4012b5:  xor    eax,eax
4012b7:  lea    rax,[rip+0xd50]        # 40200e &amp;lt;_IO_stdin_used+0xe&amp;gt;
4012be:  mov    BYTE PTR [rbp-0x61],al
4012c1:  movsx  rax,BYTE PTR [rbp-0x61]
4012c6:  mov    rdx,rax
4012c9:  mov    rax,QWORD PTR [rbp-0x60]
4012cd:  mov    rsi,rdx
4012d0:  mov    rdi,rax
4012d3:  call   4010f0 &amp;lt;strcpy@plt&amp;gt;
4012d8:  mov    rax,QWORD PTR [rbp-0x60]
4012dc:  mov    rsi,rax
4012df:  lea    rax,[rip+0xd2f]        # 402015 &amp;lt;_IO_stdin_used+0x15&amp;gt;
4012e6:  mov    rdi,rax
4012e9:  mov    eax,0x0
4012ee:  call   401130 &amp;lt;printf@plt&amp;gt;
4012f3:  nop
4012f4:  mov    rax,QWORD PTR [rbp-0x8]
4012f8:  sub    rax,QWORD PTR fs:0x28
401301:  je     401308 &amp;lt;test2+0x6c&amp;gt;
401303:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
401308:  leave
401309:  ret

000000000040130a &amp;lt;handle_client&amp;gt;:
40130a:  endbr64
40130e:  push   rbp
40130f:  mov    rbp,rsp
401312:  sub    rsp,0x170
401319:  mov    DWORD PTR [rbp-0x164],edi
40131f:  mov    rax,QWORD PTR fs:0x28
401328:  mov    QWORD PTR [rbp-0x8],rax
40132c:  xor    eax,eax
40132e:  lea    rsi,[rbp-0x110]
401335:  mov    eax,DWORD PTR [rbp-0x164]
40133b:  mov    ecx,0x0
401340:  mov    edx,0xff
401345:  mov    edi,eax
401347:  call   4010e0 &amp;lt;recv@plt&amp;gt;
40134c:  mov    DWORD PTR [rbp-0x154],eax
401352:  cmp    DWORD PTR [rbp-0x154],0x0
401359:  jle    4013b6 &amp;lt;handle_client+0xac&amp;gt;
40135b:  mov    eax,DWORD PTR [rbp-0x154]
401361:  cdqe
401363:  mov    BYTE PTR [rbp+rax*1-0x110],0x0
40136b:  lea    rdx,[rbp-0x110]
401372:  lea    rax,[rbp-0x150]
401379:  mov    rsi,rdx
40137c:  mov    rdi,rax
40137f:  call   4010f0 &amp;lt;strcpy@plt&amp;gt;
401384:  lea    rax,[rbp-0x150]
40138b:  mov    rsi,rax
40138e:  lea    rax,[rip+0xc83]        # 402018 &amp;lt;_IO_stdin_used+0x18&amp;gt;
401395:  mov    rdi,rax
401398:  mov    eax,0x0
40139d:  call   401130 &amp;lt;printf@plt&amp;gt;
4013a2:  mov    eax,0x0
4013a7:  call   401276 &amp;lt;test1&amp;gt;
4013ac:  mov    eax,0x0
4013b1:  call   40129c &amp;lt;test2&amp;gt;
4013b6:  mov    eax,DWORD PTR [rbp-0x164]
4013bc:  mov    edi,eax
4013be:  call   401140 &amp;lt;close@plt&amp;gt;
4013c3:  nop
4013c4:  mov    rax,QWORD PTR [rbp-0x8]
4013c8:  sub    rax,QWORD PTR fs:0x28
4013d1:  je     4013d8 &amp;lt;handle_client+0xce&amp;gt;
4013d3:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
4013d8:  leave
4013d9:  ret

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see here, handle_client , test2 are protected  but not test1&lt;/p&gt;

&lt;h3&gt;
  
  
  5. fstack-protector-all
&lt;/h3&gt;

&lt;p&gt;Let's see what the man page says about the option &lt;br&gt;
  -fstack-protector-all&lt;br&gt;
      Like -fstack-protector except that all functions are&lt;br&gt;
      protected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401276 &amp;lt;test1&amp;gt;:
401276:  endbr64
40127a:  push   rbp
40127b:  mov    rbp,rsp
40127e:  sub    rsp,0x10
401282:  mov    rax,QWORD PTR fs:0x28
40128b:  mov    QWORD PTR [rbp-0x8],rax
40128f:  xor    eax,eax
401291:  lea    rax,[rip+0xd70]        # 402008 &amp;lt;_IO_stdin_used+0x8&amp;gt;
401298:  mov    QWORD PTR [rbp-0x10],rax
40129c:  mov    rax,QWORD PTR [rbp-0x10]
4012a0:  mov    rdi,rax
4012a3:  call   401100 &amp;lt;puts@plt&amp;gt;
4012a8:  nop
4012a9:  mov    rax,QWORD PTR [rbp-0x8]
4012ad:  sub    rax,QWORD PTR fs:0x28
4012b6:  je     4012bd &amp;lt;test1+0x47&amp;gt;
4012b8:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
4012bd:  leave
4012be:  ret

00000000004012bf &amp;lt;test2&amp;gt;:
4012bf:  endbr64
4012c3:  push   rbp
4012c4:  mov    rbp,rsp
4012c7:  sub    rsp,0x70
4012cb:  mov    rax,QWORD PTR fs:0x28
4012d4:  mov    QWORD PTR [rbp-0x8],rax
4012d8:  xor    eax,eax
4012da:  lea    rax,[rip+0xd2d]        # 40200e &amp;lt;_IO_stdin_used+0xe&amp;gt;
4012e1:  mov    BYTE PTR [rbp-0x61],al
4012e4:  movsx  rax,BYTE PTR [rbp-0x61]
4012e9:  mov    rdx,rax
4012ec:  mov    rax,QWORD PTR [rbp-0x60]
4012f0:  mov    rsi,rdx
4012f3:  mov    rdi,rax
4012f6:  call   4010f0 &amp;lt;strcpy@plt&amp;gt;
4012fb:  movsx  eax,BYTE PTR [rbp-0x61]
4012ff:  mov    esi,eax
401301:  lea    rax,[rip+0xd0d]        # 402015 &amp;lt;_IO_stdin_used+0x15&amp;gt;
401308:  mov    rdi,rax
40130b:  mov    eax,0x0
401310:  call   401130 &amp;lt;printf@plt&amp;gt;
401315:  nop
401316:  mov    rax,QWORD PTR [rbp-0x8]
40131a:  sub    rax,QWORD PTR fs:0x28
401323:  je     40132a &amp;lt;test2+0x6b&amp;gt;
401325:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
40132a:  leave
40132b:  ret

000000000040132c &amp;lt;handle_client&amp;gt;:
40132c:  endbr64
401330:  push   rbp
401331:  mov    rbp,rsp
401334:  sub    rsp,0x170
40133b:  mov    DWORD PTR [rbp-0x164],edi
401341:  mov    rax,QWORD PTR fs:0x28
40134a:  mov    QWORD PTR [rbp-0x8],rax
40134e:  xor    eax,eax
401350:  lea    rsi,[rbp-0x110]
401357:  mov    eax,DWORD PTR [rbp-0x164]
40135d:  mov    ecx,0x0
401362:  mov    edx,0xff
401367:  mov    edi,eax
401369:  call   4010e0 &amp;lt;recv@plt&amp;gt;
40136e:  mov    DWORD PTR [rbp-0x154],eax
401374:  cmp    DWORD PTR [rbp-0x154],0x0
40137b:  jle    4013d8 &amp;lt;handle_client+0xac&amp;gt;
40137d:  mov    eax,DWORD PTR [rbp-0x154]
401383:  cdqe
401385:  mov    BYTE PTR [rbp+rax*1-0x110],0x0
40138d:  lea    rdx,[rbp-0x110]
401394:  lea    rax,[rbp-0x150]
40139b:  mov    rsi,rdx
40139e:  mov    rdi,rax
4013a1:  call   4010f0 &amp;lt;strcpy@plt&amp;gt;
4013a6:  lea    rax,[rbp-0x150]
4013ad:  mov    rsi,rax
4013b0:  lea    rax,[rip+0xc63]        # 40201a &amp;lt;_IO_stdin_used+0x1a&amp;gt;
4013b7:  mov    rdi,rax
4013ba:  mov    eax,0x0
4013bf:  call   401130 &amp;lt;printf@plt&amp;gt;
4013c4:  mov    eax,0x0
4013c9:  call   401276 &amp;lt;test1&amp;gt;
4013ce:  mov    eax,0x0
4013d3:  call   4012bf &amp;lt;test2&amp;gt;
4013d8:  mov    eax,DWORD PTR [rbp-0x164]
4013de:  mov    edi,eax
4013e0:  call   401140 &amp;lt;close@plt&amp;gt;
4013e5:  nop
4013e6:  mov    rax,QWORD PTR [rbp-0x8]
4013ea:  sub    rax,QWORD PTR fs:0x28
4013f3:  je     4013fa &amp;lt;handle_client+0xce&amp;gt;
4013f5:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
4013fa:  leave
4013fb:  ret

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see here, handle_client , test2 and test1 are protected  &lt;/p&gt;

&lt;h3&gt;
  
  
  6. Default option
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401276 &amp;lt;test1&amp;gt;:
401276:  endbr64
40127a:  push   rbp
40127b:  mov    rbp,rsp
40127e:  sub    rsp,0x10
401282:  lea    rax,[rip+0xd7f]        # 402008 &amp;lt;_IO_stdin_used+0x8&amp;gt;
401289:  mov    QWORD PTR [rbp-0x8],rax
40128d:  mov    rax,QWORD PTR [rbp-0x8]
401291:  mov    rdi,rax
401294:  call   401100 &amp;lt;puts@plt&amp;gt;
401299:  nop
40129a:  leave
40129b:  ret

000000000040129c &amp;lt;test2&amp;gt;:
40129c:  endbr64
4012a0:  push   rbp
4012a1:  mov    rbp,rsp
4012a4:  sub    rsp,0x70
4012a8:  mov    rax,QWORD PTR fs:0x28
4012b1:  mov    QWORD PTR [rbp-0x8],rax
4012b5:  xor    eax,eax
4012b7:  lea    rax,[rip+0xd50]        # 40200e &amp;lt;_IO_stdin_used+0xe&amp;gt;
4012be:  mov    BYTE PTR [rbp-0x61],al
4012c1:  movsx  rax,BYTE PTR [rbp-0x61]
4012c6:  mov    rdx,rax
4012c9:  mov    rax,QWORD PTR [rbp-0x60]
4012cd:  mov    rsi,rdx
4012d0:  mov    rdi,rax
4012d3:  call   4010f0 &amp;lt;strcpy@plt&amp;gt;
4012d8:  mov    rax,QWORD PTR [rbp-0x60]
4012dc:  mov    rsi,rax
4012df:  lea    rax,[rip+0xd2f]        # 402015 &amp;lt;_IO_stdin_used+0x15&amp;gt;
4012e6:  mov    rdi,rax
4012e9:  mov    eax,0x0
4012ee:  call   401130 &amp;lt;printf@plt&amp;gt;
4012f3:  nop
4012f4:  mov    rax,QWORD PTR [rbp-0x8]
4012f8:  sub    rax,QWORD PTR fs:0x28
401301:  je     401308 &amp;lt;test2+0x6c&amp;gt;
401303:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
401308:  leave
401309:  ret

000000000040130a &amp;lt;handle_client&amp;gt;:
40130a:  endbr64
40130e:  push   rbp
40130f:  mov    rbp,rsp
401312:  sub    rsp,0x170
401319:  mov    DWORD PTR [rbp-0x164],edi
40131f:  mov    rax,QWORD PTR fs:0x28
401328:  mov    QWORD PTR [rbp-0x8],rax
40132c:  xor    eax,eax
40132e:  lea    rsi,[rbp-0x110]
401335:  mov    eax,DWORD PTR [rbp-0x164]
40133b:  mov    ecx,0x0
401340:  mov    edx,0xff
401345:  mov    edi,eax
401347:  call   4010e0 &amp;lt;recv@plt&amp;gt;
40134c:  mov    DWORD PTR [rbp-0x154],eax
401352:  cmp    DWORD PTR [rbp-0x154],0x0
401359:  jle    4013b6 &amp;lt;handle_client+0xac&amp;gt;
40135b:  mov    eax,DWORD PTR [rbp-0x154]
401361:  cdqe
401363:  mov    BYTE PTR [rbp+rax*1-0x110],0x0
40136b:  lea    rdx,[rbp-0x110]
401372:  lea    rax,[rbp-0x150]
401379:  mov    rsi,rdx
40137c:  mov    rdi,rax
40137f:  call   4010f0 &amp;lt;strcpy@plt&amp;gt;
401384:  lea    rax,[rbp-0x150]
40138b:  mov    rsi,rax
40138e:  lea    rax,[rip+0xc83]        # 402018 &amp;lt;_IO_stdin_used+0x18&amp;gt;
401395:  mov    rdi,rax
401398:  mov    eax,0x0
40139d:  call   401130 &amp;lt;printf@plt&amp;gt;
4013a2:  mov    eax,0x0
4013a7:  call   401276 &amp;lt;test1&amp;gt;
4013ac:  mov    eax,0x0
4013b1:  call   40129c &amp;lt;test2&amp;gt;
4013b6:  mov    eax,DWORD PTR [rbp-0x164]
4013bc:  mov    edi,eax
4013be:  call   401140 &amp;lt;close@plt&amp;gt;
4013c3:  nop
4013c4:  mov    rax,QWORD PTR [rbp-0x8]
4013c8:  sub    rax,QWORD PTR fs:0x28
4013d1:  je     4013d8 &amp;lt;handle_client+0xce&amp;gt;
4013d3:  call   401110 &amp;lt;__stack_chk_fail@plt&amp;gt;
4013d8:  leave
4013d9:  ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see above, the default GCC option seems to correspond to -fstack-protector-strong  &lt;/p&gt;

&lt;h3&gt;
  
  
  7. Some history
&lt;/h3&gt;

&lt;p&gt;The -fstack-protector option was introduced into GCC in 2005, specifically with the release of GCC 4.1.&lt;/p&gt;

&lt;p&gt;Pre-2005: Before this native GCC integration, developers who wanted stack protection had to rely on a patch for GCC called "StackGuard" (originally developed by Crispin Cowan and his team at the Oregon Graduate Institute in the late 1990s). StackGuard was the pioneering implementation that popularized the "canary" concept.&lt;/p&gt;

&lt;p&gt;2005 (GCC 4.1): GCC officially integrated the functionality, making it a standard compiler feature rather than a third-party patch. This was a major milestone for security because it made hardening binaries accessible to the entire open-source ecosystem without requiring custom compiler builds.&lt;/p&gt;

&lt;p&gt;Evolution (GCC 4.9+): While the original -fstack-protector existed in 4.1, GCC later introduced more granular levels to balance security and performance:&lt;/p&gt;

&lt;p&gt;-fstack-protector-strong (added in GCC 4.9, 2014): Protects functions that have local arrays or references to local stack variables, providing a better middle ground.&lt;/p&gt;

&lt;p&gt;-fstack-protector-all: The "paranoid" mode that protects every single function, regardless of its local variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. The situation now
&lt;/h3&gt;

&lt;p&gt;With the -fstack-protector-strong option activated by default, we should not find stack buffer overflows in the CVE database. However we still find a lot of them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff4rdj1d2qyrxdq7dtx9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff4rdj1d2qyrxdq7dtx9c.png" alt=" " width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if we search for "Stack-based Buffer Overflow Remote Code Execution" we still find 437 CVE like the following one&lt;/p&gt;

&lt;p&gt;Updated: 2026-03-19&lt;/p&gt;

&lt;p&gt;Published: 2026-02-02&lt;br&gt;
Title: Libsoup: stack-based buffer overflow in libsoup multipart response parsingmultipart http response&lt;/p&gt;

&lt;p&gt;Description&lt;br&gt;
A flaw was found in libsoup. This stack-based buffer overflow vulnerability occurs during the parsing of multipart HTTP responses due to an incorrect length calculation. A remote attacker can exploit this by sending a specially crafted multipart HTTP response, which can lead to memory corruption. This issue may result in application crashes or arbitrary code execution in applications that process untrusted server responses, and it does not require authentication or user interaction.&lt;/p&gt;

&lt;p&gt;if we search for "Stack-based Buffer Overflow" we find 5809 CVE like the following one&lt;/p&gt;

&lt;p&gt;For example&lt;/p&gt;

&lt;p&gt;Updated: 2026-06-29&lt;/p&gt;

&lt;p&gt;Published: 2026-05-20&lt;br&gt;
Title: Libsolv: stack-based buffer overflow in libsolv's debian metadata parser when handling sha384/sha512 checksums&lt;/p&gt;

&lt;p&gt;Description&lt;br&gt;
A flaw was found in libsolv. This stack-based buffer overflow vulnerability occurs in libsolv's Debian metadata parser when processing specially crafted Debian repository metadata. An attacker could exploit this by providing malicious SHA384 or SHA512 checksum tags, leading to memory corruption and a denial of service (DoS) in the affected system.&lt;/p&gt;

&lt;p&gt;Even when a function is hardened with a stack canary, it remains blind to vulnerabilities occurring within the heap or logic errors that corrupt data pointers before the canary check is ever reached&lt;/p&gt;

&lt;p&gt;if we search for "Buffer Overflow" we find 22018 CVE most of them being heap buffer overflows&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Why so ?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The "Non-Stack" Overflows
The canary only protects the Return Address on the stack. It does nothing to stop overflows that target other critical data structures:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Heap Overflows: If the buffer is allocated via malloc, the canary is not involved. Attackers target metadata (like chunk headers in glibc) or function pointers stored in the heap to hijack execution.&lt;/p&gt;

&lt;p&gt;Global Data Overflows: Overwriting global variables, pointers, or flags in the .data or .bss segments doesn't trigger the stack canary.&lt;/p&gt;

&lt;p&gt;Struct Overwriting: If you have two local variables (e.g., a buffer followed by a function pointer) on the stack, an attacker can overflow the buffer to overwrite the pointer before reaching the canary. The function will use the corrupted pointer, and the program will never reach the "canary check" epilogue.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Legacy Burden (The "Unprotected" World)
Millions of lines of C/C++ code: Much of the critical infrastructure (drivers, legacy embedded systems, older enterprise software) was written long before 2014. Migrating this code to compile with modern security flags is a massive, risky, and often prohibitively expensive task.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Non-GCC Compilers: Many specialized environments (embedded firmware, proprietary real-time operating systems) use custom or older compilers that do not have stack-protector-strong implemented or enabled by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Epilogue
&lt;/h3&gt;

&lt;p&gt;By disassembling the binary (with objdump), one precisely see what gcc creates during the compilation process.  In this article, I explained the main options one can use to protect a program from a buffer overflow attack. There are several other options  (-fstack-protector-explicit, -fstack-check, -fstack-clash-protection) to precisely manage the response to a stack smash attack.&lt;/p&gt;

&lt;p&gt;Even if the default GCC option protects programs compiled with GCC from stack buffer overflows, there are still plenty of them found in the CVE database which shows that we can't rely on default protections to feel secure. &lt;/p&gt;

&lt;p&gt;In the next articles of this series, I will continue to study the options GCC offers to protect a binary from attackers.   &lt;/p&gt;

</description>
      <category>c</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>MIPS From Source Code to Binary: What Does GCC Actually Do ?</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Fri, 17 Jul 2026 08:28:38 +0000</pubDate>
      <link>https://dev.to/ddupard/-mips-from-source-code-to-binary-what-does-gcc-actually-do--20pm</link>
      <guid>https://dev.to/ddupard/-mips-from-source-code-to-binary-what-does-gcc-actually-do--20pm</guid>
      <description>&lt;p&gt;Comparing C source code with its machine-level translation is an invaluable exercise for any developer or security researcher. Compilation is not a mere literal translation; it is an optimization process where the compiler often prioritizes portability and robustness over the use of direct, specialized processor instructions. To illustrate this, we are going to use a simple program which will be compiled for a MIPS processor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;


&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test_floating_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// C'est ici qu'on verra si le compilateur génère 'abs.s'&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fabsf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FABS of %f is %f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;test_floating_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;14159&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands to compile this program are the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  mips-linux-gnu-gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fno-stack-protector&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt; &lt;span class="nt"&gt;-march&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mips32 &lt;span class="nt"&gt;-mabi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;32 &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT_MIPS&lt;/span&gt;&lt;span class="s2"&gt;/tests/mips1"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/mips1.c"&lt;/span&gt;
  mips-linux-gnu-objdump &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-M&lt;/span&gt; reg-names&lt;span class="o"&gt;=&lt;/span&gt;32 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT_MIPS&lt;/span&gt;&lt;span class="s2"&gt;/tests/mips1"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT_MIPS&lt;/span&gt;&lt;span class="s2"&gt;/tests/mips1.mips"&lt;/span&gt;
  mips-linux-gnu-readelf &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT_MIPS&lt;/span&gt;&lt;span class="s2"&gt;/tests/mips1"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT_MIPS&lt;/span&gt;&lt;span class="s2"&gt;/tests/mips1.mips_elf"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and below the assembly&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00400650 &amp;lt;test_floating_point&amp;gt;:
  400650:   27bdffc8    addiu   sp,sp,-56
  400654:   afbf0034    sw  ra,52(sp)
  400658:   afbe0030    sw  s8,48(sp)
  40065c:   03a0f025    move    s8,sp
  400660:   3c1c0043    lui gp,0x43
  400664:   279c8010    addiu   gp,gp,-32752
  400668:   afbc0018    sw  gp,24(sp)
  40066c:   e7cc0038    swc1    fa0,56(s8)
  400670:   8fc30038    lw  v1,56(s8)
  400674:   3c027fff    lui v0,0x7fff
  400678:   3442ffff    ori v0,v0,0xffff
  40067c:   00621024    and v0,v1,v0
  400680:   afc20020    sw  v0,32(s8)
  400684:   c7c00038    lwc1    fv0,56(s8)
  400688:   460000a1    cvt.d.s fv1,fv0
  40068c:   c7c00020    lwc1    fv0,32(s8)
  400690:   46000021    cvt.d.s fv0,fv0
  400694:   f7a00010    sdc1    fv0,16(sp)
  400698:   f7c20028    sdc1    fv1,40(s8)
  40069c:   8fc7002c    lw  a3,44(s8)
  4006a0:   8fc60028    lw  a2,40(s8)
  4006a4:   3c020040    lui v0,0x40
  4006a8:   24440790    addiu   a0,v0,1936
  4006ac:   8f828024    lw  v0,-32732(gp)
  4006b0:   0040c825    move    t9,v0
  4006b4:   0320f809    jalr    t9
  4006b8:   00000000    nop
  4006bc:   8fdc0018    lw  gp,24(s8)
  4006c0:   00000000    nop
  4006c4:   03c0e825    move    sp,s8
  4006c8:   8fbf0034    lw  ra,52(sp)
  4006cc:   8fbe0030    lw  s8,48(sp)
  4006d0:   27bd0038    addiu   sp,sp,56
  4006d4:   03e00008    jr  ra
  4006d8:   00000000    nop

004006dc &amp;lt;main&amp;gt;:
  4006dc:   27bdffe0    addiu   sp,sp,-32
  4006e0:   afbf001c    sw  ra,28(sp)
  4006e4:   afbe0018    sw  s8,24(sp)
  4006e8:   03a0f025    move    s8,sp
  4006ec:   3c020040    lui v0,0x40
  4006f0:   c44007a4    lwc1    fv0,1956(v0)
  4006f4:   46000306    mov.s   fa0,fv0
  4006f8:   0c100194    jal 400650 &amp;lt;test_floating_point&amp;gt;
  4006fc:   00000000    nop
  400700:   00001025    move    v0,zero
  400704:   03c0e825    move    sp,s8
  400708:   8fbf001c    lw  ra,28(sp)
  40070c:   8fbe0018    lw  s8,24(sp)
  400710:   27bd0020    addiu   sp,sp,32
  400714:   03e00008    jr  ra
  400718:   00000000    nop
  40071c:   00000000    nop

Disassembly of section .MIPS.stubs:

00400720 &amp;lt;_MIPS_STUBS_&amp;gt;:
  400720:   8f998010    lw  t9,-32752(gp)
  400724:   03e07825    move    t7,ra
  400728:   0320f809    jalr    t9
  40072c:   24180009    li  t8,9
  400730:   8f998010    lw  t9,-32752(gp)
  400734:   03e07825    move    t7,ra
  400738:   0320f809    jalr    t9
  40073c:   24180007    li  t8,7
    ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and a part of the elf&lt;/p&gt;

&lt;h5&gt;
  
  
  Global entries
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address&lt;/th&gt;
&lt;th&gt;Access&lt;/th&gt;
&lt;th&gt;Initial&lt;/th&gt;
&lt;th&gt;Sym.Val.&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Ndx&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0042002c&lt;/td&gt;
&lt;td&gt;-32740(gp)&lt;/td&gt;
&lt;td&gt;00000000&lt;/td&gt;
&lt;td&gt;00000000&lt;/td&gt;
&lt;td&gt;NOTYPE&lt;/td&gt;
&lt;td&gt;UND&lt;/td&gt;
&lt;td&gt;_ITM_registerTMCloneTable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;00420030&lt;/td&gt;
&lt;td&gt;-32736(gp)&lt;/td&gt;
&lt;td&gt;00000000&lt;/td&gt;
&lt;td&gt;00000000&lt;/td&gt;
&lt;td&gt;FUNC&lt;/td&gt;
&lt;td&gt;UND&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;gmon_start&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;00420034&lt;/td&gt;
&lt;td&gt;-32732(gp)&lt;/td&gt;
&lt;td&gt;00400730&lt;/td&gt;
&lt;td&gt;00400730&lt;/td&gt;
&lt;td&gt;FUNC&lt;/td&gt;
&lt;td&gt;UND&lt;/td&gt;
&lt;td&gt;printf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;00420038&lt;/td&gt;
&lt;td&gt;-32728(gp)&lt;/td&gt;
&lt;td&gt;00000000&lt;/td&gt;
&lt;td&gt;00000000&lt;/td&gt;
&lt;td&gt;NOTYPE&lt;/td&gt;
&lt;td&gt;UND&lt;/td&gt;
&lt;td&gt;_ITM_deregisterTMCloneTable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0042003c&lt;/td&gt;
&lt;td&gt;-32724(gp)&lt;/td&gt;
&lt;td&gt;00400720&lt;/td&gt;
&lt;td&gt;00400720&lt;/td&gt;
&lt;td&gt;FUNC&lt;/td&gt;
&lt;td&gt;UND&lt;/td&gt;
&lt;td&gt;__libc_start_main&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  1. why it is interesting ?
&lt;/h3&gt;

&lt;p&gt;To understand, you have to know that the MIPS® Architecture For Programmers Volume II-A  which is the reference for the instructions set of the mips processor contains  very specific instructions to calculate the absolute value of a floating point. In fact it contains 3 specific instructions&lt;br&gt;
ABS.S&lt;br&gt;
ABS.D&lt;br&gt;
ABS.PS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz98gjjeh6lskuvsl5z65.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz98gjjeh6lskuvsl5z65.png" alt=" " width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pages.hmc.edu/harris/class/e155/11/MIPS32InstructionSet.pdf" rel="noopener noreferrer"&gt;Instruction Set&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;so we should find one of these instructions in the test_floating_point function. we don't find any of these instructions, instead we find&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;400674: 3c027fff    lui v0,0x7fff       # v0 = 0x7fff0000
400678: 3442ffff    ori v0,v0,0xffff    # v0 = 0x7fffffff
40067c: 00621024    and v0,v1,v0        # v0 = v1 &amp;amp; 0x7fffffff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler applied a fundamental property of the IEEE 754 format here: a 32-bit floating-point number consists of one sign bit, eight exponent bits, and 23 mantissa bits. To calculate the absolute value, it is sufficient to force the sign bit to 0. This is exactly what the AND operation with 0x7FFFFFFF performs.&lt;br&gt;
As seen with this example, the compiler often generates code compatible with multiple FPU variants, or even "Soft-Float" modes, to avoid creating overly strict dependencies on specific hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Epilogue
&lt;/h3&gt;

&lt;p&gt;In this very short article we explained a very specific point of what gcc does when it compiles a C source code. This shows why disassembling a binary compiled with gcc is always interesting. As a reverser, this analysis teaches us a crucial lesson: never rely solely on an architecture's theoretical documentation. Real code is the result of a chemistry between the processor manual, the ABI (Application Binary Interface) rules, and the compiler's optimization choices.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>X86_64 From Source Code to Binary: What Does GCC Actually Do? part 2</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Wed, 08 Jul 2026 22:32:40 +0000</pubDate>
      <link>https://dev.to/ddupard/from-source-code-to-binary-what-does-gcc-actually-do-part-2-4lhp</link>
      <guid>https://dev.to/ddupard/from-source-code-to-binary-what-does-gcc-actually-do-part-2-4lhp</guid>
      <description>&lt;p&gt;In the last part of my first article on how GCC compiles, I explained the System V AMD64 ABI convention for passing parameters, it's time to explain how a function returns a result. But before that, I am going to explain the mechanism used by GCC to allocate some space in stack memory. Stack memory is a built in mechanism for x86 processors. It comes with specific instructions (push , pop ) to save and restore some data and a specific register rsp ( stack pointer register). It is used by compilers (like GCC) to store local data in functions  &lt;/p&gt;

&lt;p&gt;To illustrate the return mechanism and the stack memory allocation, I will use the following program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Return via register (Standard scalar type)&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;return_integer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Return via hidden pointer (Large struct)&lt;/span&gt;
&lt;span class="c1"&gt;// The caller provides a memory address where the result should be stored&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;LargeData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;LargeData&lt;/span&gt; &lt;span class="nf"&gt;return_large_struct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;LargeData&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// 3. Return via multiple registers (Small struct optimization)&lt;/span&gt;
&lt;span class="c1"&gt;// On x86_64, GCC places 'first' in RAX and 'second' in RDX&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;PairOfLongs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;PairOfLongs&lt;/span&gt; &lt;span class="nf"&gt;return_pair&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PairOfLongs&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;return_integer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;LargeData&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;return_large_struct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;PairOfLongs&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;return_pair&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Integer: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Large: %ld, %ld&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ld&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pair: %ld, %ld&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This program will be compiled with GCC and the binary generated will be disassembled by objdump using the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fno-stack-protector&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; a3 ./a3.c
objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; a3 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; a3.objdump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The option ( -M intel ) forces the intel convention in the disassembling process. I prefer the intel convetion over the ATT convention. &lt;/p&gt;

&lt;h3&gt;
  
  
  1.  Stack memory allocation
&lt;/h3&gt;

&lt;p&gt;Most of the functions compiled with gcc start with the same 4 lines (see below)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00000000004011bc &amp;lt;main&amp;gt;:
  4011bc:   f3 0f 1e fa             endbr64
  4011c0:   55                      push   rbp
  4011c1:   48 89 e5                mov    rbp,rsp
  4011c4:   48 83 ec 40             sub    rsp,0x40

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;endbr64&lt;/strong&gt; (end branch 64 bits) is a security checkpoint used by modern INTEL and AMD processors, It is part of a hardware protection technology called Control-flow Enforcement Technology (CET). It stops "Jump-Oriented Programming" (JOP): Attackers often try to redirect the flow of a program to existing snippets of code to do things they weren't designed to do. endbr64 prevents these unauthorized redirects. It’s a hardware-level gate because it is checked directly by the processor. We will come back on this subject in another article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;push   rbp&lt;/strong&gt; save the base pointer register to the stack&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mov    rbp,rsp&lt;/strong&gt; stores the value of the stack pointer register to the base pointer register. By doing this we create a stack frame. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sub    rsp,0x40&lt;/strong&gt; allocates a certain amount of memory for the variables of the function (here 0x40 = 64 bytes). GCC computes the necessary space for all the variables declared in the function and allocates some stack memory space by changing the value of the stack pointer register (rsp). One can save some data to the stack by the push instruction ( ex push rax ) and can retrieve data from the stack by using the pop instruction ( ex pop rax). push and pop modifies the stack pointer register (rsp), push by decreasing its value, and pop by increasing its value. The stack pointer register stores 64 bits values on a 64 bit OS, 32 bits values on 32 bits OS, etc.    &lt;/p&gt;

&lt;h3&gt;
  
  
  2.  How a function compiled by GCC returns some result
&lt;/h3&gt;

&lt;p&gt;Depending on the size of the results returned, GCC uses one of the following 3 mechanisms:&lt;br&gt;
1) the result is returned by a register (RAX, EAX, AX, AL)&lt;br&gt;
2) the result is returned by a hidden pointer&lt;br&gt;
3) the result is returned on several registers (for floating pointers)&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Return by a register
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401136 &amp;lt;return_integer&amp;gt;:
  401136:   f3 0f 1e fa             endbr64
  40113a:   55                      push   rbp
  40113b:   48 89 e5                mov    rbp,rsp
  40113e:   b8 2a 00 00 00          mov    eax,0x2a
  401143:   5d                      pop    rbp
  401144:   c3                      ret

00000000004011bc &amp;lt;main&amp;gt;:
  ...
  4011c8:   b8 00 00 00 00          mov    eax,0x0
  4011cd:   e8 64 ff ff ff          call   401136 &amp;lt;return_integer&amp;gt;
  4011d2:   89 45 fc                mov    DWORD PTR [rbp-0x4],eax
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the most common return mechanism, a value is returned by a single register (here eax). Notice that even in a 64 bits OS, the value returned can be a 64 bits value, a 32 bits value, a 16 bits value or even a 8 bits value. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mov    DWORD PTR [rbp-0x4],eax&lt;/strong&gt; moves the value of the register eax (the result of the function return_integer) to a specific memory location in the stack &lt;/p&gt;
&lt;h3&gt;
  
  
  2. Return by a hidden pointer
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
0000000000401145 &amp;lt;return_large_struct&amp;gt;:
  401145:   f3 0f 1e fa             endbr64
  401149:   55                      push   rbp
  40114a:   48 89 e5                mov    rbp,rsp
  40114d:   48 89 7d d8             mov    QWORD PTR [rbp-0x28],rdi
  401151:   48 c7 45 e0 01 00 00    mov    QWORD PTR [rbp-0x20],0x1
  401158:   00 
  401159:   48 c7 45 e8 02 00 00    mov    QWORD PTR [rbp-0x18],0x2
  401160:   00 
  401161:   48 c7 45 f0 03 00 00    mov    QWORD PTR [rbp-0x10],0x3
  401168:   00 
  401169:   48 c7 45 f8 04 00 00    mov    QWORD PTR [rbp-0x8],0x4
  401170:   00 
  401171:   48 8b 4d d8             mov    rcx,QWORD PTR [rbp-0x28]
  401175:   48 8b 45 e0             mov    rax,QWORD PTR [rbp-0x20]
  401179:   48 8b 55 e8             mov    rdx,QWORD PTR [rbp-0x18]
  40117d:   48 89 01                mov    QWORD PTR [rcx],rax
  401180:   48 89 51 08             mov    QWORD PTR [rcx+0x8],rdx
  401184:   48 8b 45 f0             mov    rax,QWORD PTR [rbp-0x10]
  401188:   48 8b 55 f8             mov    rdx,QWORD PTR [rbp-0x8]
  40118c:   48 89 41 10             mov    QWORD PTR [rcx+0x10],rax
  401190:   48 89 51 18             mov    QWORD PTR [rcx+0x18],rdx
  401194:   48 8b 45 d8             mov    rax,QWORD PTR [rbp-0x28]
  401198:   5d                      pop    rbp
  401199:   c3                      ret


00000000004011bc &amp;lt;main&amp;gt;:
  ...
  4011d5:   48 8d 45 d0             lea    rax,[rbp-0x30]
  4011d9:   48 89 c7                mov    rdi,rax
  4011dc:   b8 00 00 00 00          mov    eax,0x0
  4011e1:   e8 5f ff ff ff          call   401145 &amp;lt;return_large_struct&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Because the result returned by the function is a large structure with a size far greater than 8 bytes, the register mechanism can't be used. &lt;br&gt;
see what happens before the call, with the 2 instructions &lt;strong&gt;lea    rax,[rbp-0x30]&lt;/strong&gt; and     &lt;strong&gt;mov    rdi,rax&lt;/strong&gt;  rdi receives rbp-0x30 which corresponds &lt;br&gt;
to an address in the stack. Even if the function return_large_struct has no parameter, rdi is filled with a value which is then used in the function return_large_struct. &lt;br&gt;
Using RDI as a pointer is why this mechanism is called the hidden pointer mechanism. &lt;/p&gt;

&lt;p&gt;In this mechanism, the called function performs zero stack allocation for the result. It treats the address provided in RDI as a raw memory pointer. The called function essentially &lt;br&gt;
acts as a 'data mover,' writing its local results directly into the memory frame that was already reserved by the caller. And in our example the caller has reserved data in the stack.&lt;/p&gt;

&lt;p&gt;The only "real" instructions of the function return_large_struct are the 4 following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  401151:   48 c7 45 e0 01 00 00    mov    QWORD PTR [rbp-0x20],0x1
  401158:   00 
  401159:   48 c7 45 e8 02 00 00    mov    QWORD PTR [rbp-0x18],0x2
  401160:   00 
  401161:   48 c7 45 f0 03 00 00    mov    QWORD PTR [rbp-0x10],0x3
  401168:   00 
  401169:   48 c7 45 f8 04 00 00    mov    QWORD PTR [rbp-0x8],0x4
  401170:   00 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, objdump prioritizes human-readable assembly over raw opcode alignment. When an instruction's length causes a mismatch with the internal column formatting, it may wrap the remaining bytes to a new line, hence 00 on a new line after the instruction line. Note that the 00 bytes appearing on separate lines are not instructions, but rather the hexadecimal representation of the immediate data values encoded directly within the machine instructions.&lt;/p&gt;

&lt;p&gt;The following lines have only one purpose: to return the information to the caller. See how the compiler uses the register rcx and the stack to store data&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  40117d:   48 89 01                mov    QWORD PTR [rcx],rax
  401180:   48 89 51 08             mov    QWORD PTR [rcx+0x8],rdx
  401184:   48 8b 45 f0             mov    rax,QWORD PTR [rbp-0x10]
  401188:   48 8b 55 f8             mov    rdx,QWORD PTR [rbp-0x8]
  40118c:   48 89 41 10             mov    QWORD PTR [rcx+0x10],rax
  401190:   48 89 51 18             mov    QWORD PTR [rcx+0x18],rdx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Return by multiple registers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;000000000040119a &amp;lt;return_pair&amp;gt;:
  40119a:   f3 0f 1e fa             endbr64
  40119e:   55                      push   rbp
  40119f:   48 89 e5                mov    rbp,rsp
  4011a2:   48 c7 45 f0 64 00 00    mov    QWORD PTR [rbp-0x10],0x64
  4011a9:   00 
  4011aa:   48 c7 45 f8 c8 00 00    mov    QWORD PTR [rbp-0x8],0xc8
  4011b1:   00 
  4011b2:   48 8b 45 f0             mov    rax,QWORD PTR [rbp-0x10]
  4011b6:   48 8b 55 f8             mov    rdx,QWORD PTR [rbp-0x8]
  4011ba:   5d                      pop    rbp
  4011bb:   c3                      ret

00000000004011bc &amp;lt;main&amp;gt;:
  ...
  4011e6:   b8 00 00 00 00          mov    eax,0x0
  4011eb:   e8 aa ff ff ff          call   40119a &amp;lt;return_pair&amp;gt;
  4011f0:   48 89 45 c0             mov    QWORD PTR [rbp-0x40],rax
  4011f4:   48 89 55 c8             mov    QWORD PTR [rbp-0x38],rdx

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here what the compiler does is pretty straightforward, it uses the registers rax and rdx to return the values to the caller function.&lt;/p&gt;

&lt;p&gt;Right now , we've seen the 3 main ways used by gcc to return values from a function. but if we use some compilation options , we'll see that a lot can change.  &lt;/p&gt;

&lt;h3&gt;
  
  
  4. what happens when we change some compilation options
&lt;/h3&gt;

&lt;p&gt;Now we are going to use the following command to compile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fno-stack-protector&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt; &lt;span class="nt"&gt;-O3&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; a3_o3 ./a3.c
objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; a3_o3 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; a3_o3.objdump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is really different from what we had previously&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
0000000000401050 &amp;lt;main&amp;gt;:
  401050:   f3 0f 1e fa             endbr64
  401054:   48 83 ec 08             sub    rsp,0x8
  401058:   ba 2a 00 00 00          mov    edx,0x2a
  40105d:   bf 02 00 00 00          mov    edi,0x2
  401062:   31 c0                   xor    eax,eax
  401064:   48 8d 35 99 0f 00 00    lea    rsi,[rip+0xf99]        # 402004 &amp;lt;_IO_stdin_used+0x4&amp;gt;
  40106b:   e8 d0 ff ff ff          call   401040 &amp;lt;__printf_chk@plt&amp;gt;
  401070:   b9 04 00 00 00          mov    ecx,0x4
  401075:   ba 01 00 00 00          mov    edx,0x1
  40107a:   31 c0                   xor    eax,eax
  40107c:   48 8d 35 8e 0f 00 00    lea    rsi,[rip+0xf8e]        # 402011 &amp;lt;_IO_stdin_used+0x11&amp;gt;
  401083:   bf 02 00 00 00          mov    edi,0x2
  401088:   e8 b3 ff ff ff          call   401040 &amp;lt;__printf_chk@plt&amp;gt;
  40108d:   b9 c8 00 00 00          mov    ecx,0xc8
  401092:   ba 64 00 00 00          mov    edx,0x64
  401097:   31 c0                   xor    eax,eax
  401099:   48 8d 35 82 0f 00 00    lea    rsi,[rip+0xf82]        # 402022 &amp;lt;_IO_stdin_used+0x22&amp;gt;
  4010a0:   bf 02 00 00 00          mov    edi,0x2
  4010a5:   e8 96 ff ff ff          call   401040 &amp;lt;__printf_chk@plt&amp;gt;
  4010aa:   31 c0                   xor    eax,eax
  4010ac:   48 83 c4 08             add    rsp,0x8
  4010b0:   c3                      ret
  4010b1:   66 2e 0f 1f 84 00 00    cs nop WORD PTR [rax+rax*1+0x0]
  4010b8:   00 00 00 
  4010bb:   0f 1f 44 00 00          nop    DWORD PTR [rax+rax*1+0x0]
...

00000000004011b0 &amp;lt;return_integer&amp;gt;:
  4011b0:   f3 0f 1e fa             endbr64
  4011b4:   b8 2a 00 00 00          mov    eax,0x2a
  4011b9:   c3                      ret
  4011ba:   66 0f 1f 44 00 00       nop    WORD PTR [rax+rax*1+0x0]

00000000004011c0 &amp;lt;return_large_struct&amp;gt;:
  4011c0:   f3 0f 1e fa             endbr64
  4011c4:   66 0f 6f 05 74 0e 00    movdqa xmm0,XMMWORD PTR [rip+0xe74]        # 402040 &amp;lt;_IO_stdin_used+0x40&amp;gt;
  4011cb:   00 
  4011cc:   48 89 f8                mov    rax,rdi
  4011cf:   0f 11 07                movups XMMWORD PTR [rdi],xmm0
  4011d2:   66 0f 6f 05 76 0e 00    movdqa xmm0,XMMWORD PTR [rip+0xe76]        # 402050 &amp;lt;_IO_stdin_used+0x50&amp;gt;
  4011d9:   00 
  4011da:   0f 11 47 10             movups XMMWORD PTR [rdi+0x10],xmm0
  4011de:   c3                      ret
  4011df:   90                      nop

00000000004011e0 &amp;lt;return_pair&amp;gt;:
  4011e0:   f3 0f 1e fa             endbr64
  4011e4:   b8 64 00 00 00          mov    eax,0x64
  4011e9:   ba c8 00 00 00          mov    edx,0xc8
  4011ee:   c3                      ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no call of the different functions in the main function because the main already contains the result of all these functions.&lt;br&gt;
With optimization (-O3): The compiler realizes, "Why call ? I'll just put the instructions for return_integer right here inside main.&lt;/p&gt;

&lt;p&gt;So if there is no call and the results of the functions have been integrated directly in the main function why do we still find the 3 functions (return_integer, return_large_struct, return_pair) in the binary ?&lt;/p&gt;

&lt;p&gt;GCC and the linker often preserve the original function code for a few critical reasons.&lt;/p&gt;
&lt;h6&gt;
  
  
  1. The "Export" Requirement (Symbol Visibility)
&lt;/h6&gt;

&lt;p&gt;By default, in C, functions have external linkage. This means that another object file or a shared library might technically be able to call return_integer. Even if your current main doesn't use the function anymore, GCC cannot guarantee that no one else will, so it keeps the code in the binary to ensure the symbol remains resolvable.&lt;/p&gt;
&lt;h6&gt;
  
  
  2. Debugging and Profiling
&lt;/h6&gt;

&lt;p&gt;If you compile with debug symbols (even if you don't use -g, some remnants remain), the linker tries to maintain a map between the source code functions and the machine code. If it deleted the function entirely, tools like gdb or perf (profilers) would not be able to "find" the function, making it impossible to step through or profile the original code.&lt;/p&gt;
&lt;h6&gt;
  
  
  3. The "Ghost" Code Phenomenon
&lt;/h6&gt;

&lt;p&gt;Think of the binary as a storage container. When you compile:&lt;/p&gt;

&lt;p&gt;GCC generates the object code for every function defined in a3.c.&lt;/p&gt;

&lt;p&gt;The linker then combines these. If you haven't explicitly asked the linker to "garbage collect" unused code (a feature called Dead Code Elimination), it will simply place all generated code into the .text section of the final binary.&lt;/p&gt;

&lt;p&gt;If you want a truly minimal binary where these "orphaned" functions are physically removed, you can use linker flags that perform Dead Code Elimination. You can add these flags to your compilation command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-O3&lt;/span&gt; &lt;span class="nt"&gt;-ffunction-sections&lt;/span&gt; &lt;span class="nt"&gt;-fdata-sections&lt;/span&gt; &lt;span class="nt"&gt;-Wl&lt;/span&gt;,--gc-sections a3.c &lt;span class="nt"&gt;-o&lt;/span&gt; a3_min
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Epilogue
&lt;/h3&gt;

&lt;p&gt;By disassembling the binary (with objdump), one precisely see what gcc creates during the compilation process.  In this article, I explained the stack allocation mechanism and the way GCC returns a result from a function and I showed that some compilations options could really change the binary code.  &lt;/p&gt;

&lt;h3&gt;
  
  
  6. Disasm of the binary generated by GCC
&lt;/h3&gt;

&lt;p&gt;Below you find the importants parts of the disassembly of the binary generated by gcc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401136 &amp;lt;return_integer&amp;gt;:
  401136:   f3 0f 1e fa             endbr64
  40113a:   55                      push   rbp
  40113b:   48 89 e5                mov    rbp,rsp
  40113e:   b8 2a 00 00 00          mov    eax,0x2a
  401143:   5d                      pop    rbp
  401144:   c3                      ret

0000000000401145 &amp;lt;return_large_struct&amp;gt;:
  401145:   f3 0f 1e fa             endbr64
  401149:   55                      push   rbp
  40114a:   48 89 e5                mov    rbp,rsp
  40114d:   48 89 7d d8             mov    QWORD PTR [rbp-0x28],rdi
  401151:   48 c7 45 e0 01 00 00    mov    QWORD PTR [rbp-0x20],0x1
  401158:   00 
  401159:   48 c7 45 e8 02 00 00    mov    QWORD PTR [rbp-0x18],0x2
  401160:   00 
  401161:   48 c7 45 f0 03 00 00    mov    QWORD PTR [rbp-0x10],0x3
  401168:   00 
  401169:   48 c7 45 f8 04 00 00    mov    QWORD PTR [rbp-0x8],0x4
  401170:   00 
  401171:   48 8b 4d d8             mov    rcx,QWORD PTR [rbp-0x28]
  401175:   48 8b 45 e0             mov    rax,QWORD PTR [rbp-0x20]
  401179:   48 8b 55 e8             mov    rdx,QWORD PTR [rbp-0x18]
  40117d:   48 89 01                mov    QWORD PTR [rcx],rax
  401180:   48 89 51 08             mov    QWORD PTR [rcx+0x8],rdx
  401184:   48 8b 45 f0             mov    rax,QWORD PTR [rbp-0x10]
  401188:   48 8b 55 f8             mov    rdx,QWORD PTR [rbp-0x8]
  40118c:   48 89 41 10             mov    QWORD PTR [rcx+0x10],rax
  401190:   48 89 51 18             mov    QWORD PTR [rcx+0x18],rdx
  401194:   48 8b 45 d8             mov    rax,QWORD PTR [rbp-0x28]
  401198:   5d                      pop    rbp
  401199:   c3                      ret

000000000040119a &amp;lt;return_pair&amp;gt;:
  40119a:   f3 0f 1e fa             endbr64
  40119e:   55                      push   rbp
  40119f:   48 89 e5                mov    rbp,rsp
  4011a2:   48 c7 45 f0 64 00 00    mov    QWORD PTR [rbp-0x10],0x64
  4011a9:   00 
  4011aa:   48 c7 45 f8 c8 00 00    mov    QWORD PTR [rbp-0x8],0xc8
  4011b1:   00 
  4011b2:   48 8b 45 f0             mov    rax,QWORD PTR [rbp-0x10]
  4011b6:   48 8b 55 f8             mov    rdx,QWORD PTR [rbp-0x8]
  4011ba:   5d                      pop    rbp
  4011bb:   c3                      ret

00000000004011bc &amp;lt;main&amp;gt;:
  4011bc:   f3 0f 1e fa             endbr64
  4011c0:   55                      push   rbp
  4011c1:   48 89 e5                mov    rbp,rsp
  4011c4:   48 83 ec 40             sub    rsp,0x40
  4011c8:   b8 00 00 00 00          mov    eax,0x0
  4011cd:   e8 64 ff ff ff          call   401136 &amp;lt;return_integer&amp;gt;
  4011d2:   89 45 fc                mov    DWORD PTR [rbp-0x4],eax
  4011d5:   48 8d 45 d0             lea    rax,[rbp-0x30]
  4011d9:   48 89 c7                mov    rdi,rax
  4011dc:   b8 00 00 00 00          mov    eax,0x0
  4011e1:   e8 5f ff ff ff          call   401145 &amp;lt;return_large_struct&amp;gt;
  4011e6:   b8 00 00 00 00          mov    eax,0x0
  4011eb:   e8 aa ff ff ff          call   40119a &amp;lt;return_pair&amp;gt;
  4011f0:   48 89 45 c0             mov    QWORD PTR [rbp-0x40],rax
  4011f4:   48 89 55 c8             mov    QWORD PTR [rbp-0x38],rdx
  4011f8:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
  4011fb:   89 c6                   mov    esi,eax
  4011fd:   48 8d 05 00 0e 00 00    lea    rax,[rip+0xe00]        # 402004 &amp;lt;_IO_stdin_used+0x4&amp;gt;
  401204:   48 89 c7                mov    rdi,rax
  401207:   b8 00 00 00 00          mov    eax,0x0
  40120c:   e8 2f fe ff ff          call   401040 &amp;lt;printf@plt&amp;gt;
  401211:   48 8b 55 e8             mov    rdx,QWORD PTR [rbp-0x18]
  401215:   48 8b 45 d0             mov    rax,QWORD PTR [rbp-0x30]
  401219:   48 89 c6                mov    rsi,rax
  40121c:   48 8d 05 ee 0d 00 00    lea    rax,[rip+0xdee]        # 402011 &amp;lt;_IO_stdin_used+0x11&amp;gt;
  401223:   48 89 c7                mov    rdi,rax
  401226:   b8 00 00 00 00          mov    eax,0x0
  40122b:   e8 10 fe ff ff          call   401040 &amp;lt;printf@plt&amp;gt;
  401230:   48 8b 55 c8             mov    rdx,QWORD PTR [rbp-0x38]
  401234:   48 8b 45 c0             mov    rax,QWORD PTR [rbp-0x40]
  401238:   48 89 c6                mov    rsi,rax
  40123b:   48 8d 05 e0 0d 00 00    lea    rax,[rip+0xde0]        # 402022 &amp;lt;_IO_stdin_used+0x22&amp;gt;
  401242:   48 89 c7                mov    rdi,rax
  401245:   b8 00 00 00 00          mov    eax,0x0
  40124a:   e8 f1 fd ff ff          call   401040 &amp;lt;printf@plt&amp;gt;
  40124f:   b8 00 00 00 00          mov    eax,0x0
  401254:   c9                      leave
  401255:   c3                      ret

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>X86_64 From Source Code to Binary: What Does GCC Actually Do?</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sat, 04 Jul 2026 07:03:24 +0000</pubDate>
      <link>https://dev.to/ddupard/from-source-code-to-binary-what-does-gcc-actually-do-dng</link>
      <guid>https://dev.to/ddupard/from-source-code-to-binary-what-does-gcc-actually-do-dng</guid>
      <description>&lt;p&gt;When we write a C program, we work with high-level concepts like functions, variables, and loops. However, your computer's processor only understands raw binary instructions. The compiler, gcc (GNU Compiler Collection), acts as a universal translator, transforming your human-readable code into machine-executable logic.&lt;/p&gt;

&lt;p&gt;To illustrate this, we use a simple program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"multiple parameters %s %i %i&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. The Invisible Compilation Journey
&lt;/h3&gt;

&lt;p&gt;gcc is not just a single tool; it is an orchestrator that runs several sequential stages:&lt;/p&gt;

&lt;p&gt;The Preprocessor: It handles directives like #include . It replaces this line with the entire content of the header file, preparing the code for compilation.&lt;/p&gt;

&lt;p&gt;Compilation: The C code is transformed into assembly language, which is a textual representation of machine instructions.&lt;/p&gt;

&lt;p&gt;Assembly: The assembler translates these instructions into binary format (object files .o).&lt;/p&gt;

&lt;p&gt;Linking: This is the crucial final step. Your code uses printf, a function belonging to the standard C library (libc). The linker connects your code to the actual addresses of these functions within the system library.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Anatomy of a Binary: From Source to Execution
&lt;/h3&gt;

&lt;p&gt;After the linking process, gcc generates an ELF File which contains several sections and several compiler-generated functions&lt;/p&gt;

&lt;h4&gt;
  
  
  A. Binary Sections: The Anatomy of the ELF File
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.init&lt;/code&gt; &amp;amp; &lt;code&gt;.fini&lt;/code&gt;&lt;/strong&gt;: These sections contain code executed before and after your &lt;code&gt;main&lt;/code&gt; function. They handle global setup and teardown.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;.plt&lt;/code&gt; (Procedure Linkage Table)&lt;/strong&gt;: This section acts as a "trampoline" for external library functions (like &lt;code&gt;printf&lt;/code&gt;). Since the exact memory address of &lt;code&gt;libc&lt;/code&gt; is determined at runtime, the &lt;code&gt;.plt&lt;/code&gt; enables dynamic linking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;.text&lt;/code&gt;&lt;/strong&gt;: This is where your actual code—the &lt;code&gt;main&lt;/code&gt; function and compiler-generated support functions—resides. It is marked as &lt;strong&gt;Read-Only and Executable&lt;/strong&gt; to prevent tampering.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  B. Compiler-Generated Functions
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;gcc&lt;/code&gt; adds several functions to your binary that you never explicitly wrote. These are essential for the program's lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;_start&lt;/code&gt;&lt;/strong&gt;: This is the real entry point of your program. It is called by the OS kernel. It initializes the environment (arguments, environment variables) and then calls &lt;code&gt;__libc_start_main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;__libc_start_main&lt;/code&gt;&lt;/strong&gt;: A standard library function that prepares the environment for your &lt;code&gt;main&lt;/code&gt; function and calls it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;register_tm_clones&lt;/code&gt; / &lt;code&gt;deregister_tm_clones&lt;/code&gt;&lt;/strong&gt;: These functions handle Transactional Memory management. They are part of the GCC runtime overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;__do_global_dtors_aux&lt;/code&gt;&lt;/strong&gt;: This function is responsible for calling destructors for global objects before the program exits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;frame_dummy&lt;/code&gt;&lt;/strong&gt;: A helper function used to register frame information for exception handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  C. Execution Flow: What Happens When You Run &lt;code&gt;./hello&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;When you launch the program from your shell, the following sequence occurs:&lt;/p&gt;

&lt;p&gt;a. &lt;strong&gt;OS Kernel Loading&lt;/strong&gt;: The Linux kernel maps the binary into memory and hands control to the dynamic linker (&lt;code&gt;ld-linux.so&lt;/code&gt;).&lt;br&gt;
b. &lt;strong&gt;&lt;code&gt;_start&lt;/code&gt;&lt;/strong&gt;: The kernel jumps to &lt;code&gt;_start&lt;/code&gt;. It cleans up the stack, sets up the initial registers, and invokes the C library's initialization logic.&lt;br&gt;
c. &lt;strong&gt;Initialization (&lt;code&gt;.init&lt;/code&gt;)&lt;/strong&gt;: The code in the &lt;code&gt;.init&lt;/code&gt; section runs, setting up the runtime environment.&lt;br&gt;
d. &lt;strong&gt;&lt;code&gt;main&lt;/code&gt; Invocation&lt;/strong&gt;: &lt;code&gt;__libc_start_main&lt;/code&gt; calls your &lt;code&gt;main&lt;/code&gt; function.&lt;br&gt;
e. &lt;strong&gt;&lt;code&gt;printf&lt;/code&gt; Execution&lt;/strong&gt;: Inside &lt;code&gt;main&lt;/code&gt;, your code calls &lt;code&gt;printf&lt;/code&gt;. It jumps to the &lt;code&gt;.plt&lt;/code&gt; entry, which resolves the library address and executes the actual print command.&lt;br&gt;
f. &lt;strong&gt;Termination&lt;/strong&gt;: After &lt;code&gt;main&lt;/code&gt; returns, the program invokes &lt;code&gt;__do_global_dtors_aux&lt;/code&gt; (to clean up globals) and the &lt;code&gt;.fini&lt;/code&gt; section, then exits by calling a kernel system call.&lt;/p&gt;
&lt;h5&gt;
  
  
  Summary Table
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Function/Section&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prepare registers and invoke &lt;code&gt;libc&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Init&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Global initializations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;main&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your custom code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Linkage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.plt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Resolving library functions (&lt;code&gt;printf&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cleanup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.fini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Final program shutdown&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  3. The Mechanics of Parameter Passing (System V AMD64 ABI Convention)
&lt;/h3&gt;

&lt;p&gt;In the C programming language, passing arguments between functions does not rely on a "magic" stack, but on a strict convention called the System V AMD64 ABI. To optimize for speed, the gcc compiler prioritizes using CPU registers before resorting to memory (the stack).&lt;/p&gt;

&lt;p&gt;When a function is called, the parameters are placed in the following specific registers, in this exact order:&lt;/p&gt;

&lt;p&gt;rdi: 1st argument&lt;br&gt;
rsi: 2nd argument&lt;br&gt;
rdx: 3rd argument&lt;br&gt;
rcx: 4th argument&lt;br&gt;
r8: 5th argument&lt;br&gt;
r9: 6th argument&lt;/p&gt;

&lt;p&gt;If your function requires more than 6 arguments, the additional parameters are then pushed onto the stack, which is significantly slower.&lt;/p&gt;

&lt;p&gt;See below for some examples of the System V AMD64 ABI mechanism&lt;/p&gt;

&lt;p&gt;In the objdump analysis of the main function, you could observe this sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401156 &amp;lt;main&amp;gt;:
  401156:   f3 0f 1e fa             endbr64
  40115a:   55                      push   %rbp
  40115b:   48 89 e5                mov    %rsp,%rbp
  40115e:   48 8d 05 9f 0e 00 00    lea    0xe9f(%rip),%rax        # 402004 &amp;lt;_IO_stdin_used+0x4&amp;gt;
  401165:   48 89 c7                mov    %rax,%rdi
  401168:   e8 e3 fe ff ff          call   401050 &amp;lt;puts@plt&amp;gt;
  40116d:   b9 02 00 00 00          mov    $0x2,%ecx
  401172:   ba 01 00 00 00          mov    $0x1,%edx
  401177:   48 8d 05 92 0e 00 00    lea    0xe92(%rip),%rax        # 402010 &amp;lt;_IO_stdin_used+0x10&amp;gt;
  40117e:   48 89 c6                mov    %rax,%rsi
  401181:   48 8d 05 8d 0e 00 00    lea    0xe8d(%rip),%rax        # 402015 &amp;lt;_IO_stdin_used+0x15&amp;gt;
  401188:   48 89 c7                mov    %rax,%rdi
  40118b:   b8 00 00 00 00          mov    $0x0,%eax
  401190:   e8 cb fe ff ff          call   401060 &amp;lt;printf@plt&amp;gt;
  401195:   b8 00 00 00 00          mov    $0x0,%eax
  40119a:   5d                      pop    %rbp
  40119b:   c3                      ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the most interesting aspects revealed by disassembly is GCC's optimization logic. For the simple string 'Hello world\n', the compiler identifies that no formatting is required and replaces the call to the more complex printf with a call to the more efficient puts function. This demonstrates that GCC is not just a translator, but an optimizer that actively refines your code for better performance.&lt;/p&gt;

&lt;p&gt;For the first instruction the compiler fills the register rdi.&lt;/p&gt;

&lt;p&gt;When calling the second printf, we can observe the compiler strictly adhering to the System V ABI. It populates the registers in the following order:&lt;/p&gt;

&lt;p&gt;rdi: Holds the address of the format string.&lt;br&gt;
rsi: Holds the address of the string argument 'test'.&lt;br&gt;
rdx: Holds the first integer (1).&lt;br&gt;
rcx: Holds the second integer (2).&lt;/p&gt;

&lt;p&gt;By analyzing the assembly, we see exactly how the compiler maps your C variables to the CPU's 'highways'."&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Epilogue
&lt;/h3&gt;

&lt;p&gt;In this very short article we explained what gcc does when it compiles a C source code.&lt;br&gt;
By disassembling your own code (with objdump), you precisely see what gcc creates during the compilation process. gcc adds control code (prologues/epilogues) and linking mechanisms (.plt, .got) that are essential for your program to communicate with the operating system. Moreover it follows a strict mechanism for passing arguments.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a comfortable workflow for debugging an old version of the Linux kernel</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Mon, 25 May 2026 01:38:52 +0000</pubDate>
      <link>https://dev.to/ddupard/building-a-comfortable-workflow-for-debugging-an-old-version-of-the-linux-kernel-557c</link>
      <guid>https://dev.to/ddupard/building-a-comfortable-workflow-for-debugging-an-old-version-of-the-linux-kernel-557c</guid>
      <description>&lt;p&gt;When you want to work on the Linux kernel, for example to see how an exploit acts (like Dirty COW on kernel 4.7), you need to build a comfortable working environment.&lt;/p&gt;

&lt;p&gt;I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; for compiling sources in their original version (with the GCC/LD versions corresponding to the source era).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QEMU&lt;/strong&gt; for running the executables in a virtual machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code&lt;/strong&gt; as a debugger.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Through this article, I will show you how I configured my environment to achieve an efficient setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) Compiling source code
&lt;/h2&gt;

&lt;p&gt;The first step is to retrieve the kernel source code.&lt;/p&gt;

&lt;p&gt;For relatively recent versions (beyond 5.10), the simplest way is to download the tar file from &lt;a href="https://www.kernel.org/" rel="noopener noreferrer"&gt;kernel.org&lt;/a&gt;. For older versions, the best solution is to fetch them via git.&lt;/p&gt;

&lt;p&gt;For example, for 4.7, we start by retrieving the tags:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;git ls-remote --tags git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | grep "v4.7"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then we clone it to get the version without downloading the entire history:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;git clone --depth 1 --branch v4.7 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 4.7&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After a few minutes, you have a &lt;code&gt;4.7/&lt;/code&gt; directory containing a working version of the 4.7 kernel sources.&lt;/p&gt;

&lt;p&gt;However, these sources are not compilable as-is. Compiling a 4.7 kernel (released in 2016) with a modern compiler (GCC 13+) produces compilation errors due to changes in C language standards or security attribute handling. This is why you need to load versions of GCC and LD compatible with these sources (see the table below), and the easiest way to do this is via Docker.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kernel Version&lt;/th&gt;
&lt;th&gt;Ubuntu Version&lt;/th&gt;
&lt;th&gt;Codename&lt;/th&gt;
&lt;th&gt;Release Date&lt;/th&gt;
&lt;th&gt;Default GCC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;v2.6.x&lt;/td&gt;
&lt;td&gt;6.06&lt;/td&gt;
&lt;td&gt;Dapper Drake&lt;/td&gt;
&lt;td&gt;June 2006&lt;/td&gt;
&lt;td&gt;GCC 4.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v3.2&lt;/td&gt;
&lt;td&gt;12.04&lt;/td&gt;
&lt;td&gt;Precise Pangolin&lt;/td&gt;
&lt;td&gt;April 2012&lt;/td&gt;
&lt;td&gt;GCC 4.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v3.13&lt;/td&gt;
&lt;td&gt;14.04&lt;/td&gt;
&lt;td&gt;Trusty Tahr&lt;/td&gt;
&lt;td&gt;April 2014&lt;/td&gt;
&lt;td&gt;GCC 4.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v4.4&lt;/td&gt;
&lt;td&gt;16.04&lt;/td&gt;
&lt;td&gt;Xenial Xerus&lt;/td&gt;
&lt;td&gt;April 2016&lt;/td&gt;
&lt;td&gt;GCC 5.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v4.15&lt;/td&gt;
&lt;td&gt;18.04&lt;/td&gt;
&lt;td&gt;Bionic Beaver&lt;/td&gt;
&lt;td&gt;April 2018&lt;/td&gt;
&lt;td&gt;GCC 7.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v5.4&lt;/td&gt;
&lt;td&gt;20.04&lt;/td&gt;
&lt;td&gt;Focal Fossa&lt;/td&gt;
&lt;td&gt;April 2020&lt;/td&gt;
&lt;td&gt;GCC 9.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v5.15&lt;/td&gt;
&lt;td&gt;22.04&lt;/td&gt;
&lt;td&gt;Jammy Jellyfish&lt;/td&gt;
&lt;td&gt;April 2022&lt;/td&gt;
&lt;td&gt;GCC 11.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v6.8&lt;/td&gt;
&lt;td&gt;24.04&lt;/td&gt;
&lt;td&gt;Noble Numbat&lt;/td&gt;
&lt;td&gt;April 2024&lt;/td&gt;
&lt;td&gt;GCC 13.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We need to retrieve the Docker container corresponding to the kernel version we are interested in. For 4.7, it is Ubuntu 16.04.&lt;/p&gt;

&lt;p&gt;To search for available containers, there are 2 solutions:&lt;br&gt;
a) Run the command:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;skopeo list-tags docker://docker.io/library/ubuntu&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;you should see something like &lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
    "Repository": "docker.io/library/ubuntu",&lt;br&gt;
    "Tags": [&lt;br&gt;
        "10.04",&lt;br&gt;
        "12.04",&lt;br&gt;
        "12.04.5",&lt;br&gt;
        "12.10",&lt;br&gt;
        "13.04",&lt;br&gt;
        "13.10",&lt;br&gt;
        "14.04",&lt;br&gt;
        "14.04.1",&lt;br&gt;
...&lt;/p&gt;

&lt;p&gt;...then run the command:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo docker pull ubuntu:16.04&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;b) Go to Docker Hub &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52j4gppztvssbvxchx44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52j4gppztvssbvxchx44.png" alt="Docker Hub" width="800" height="394"&gt;&lt;/a&gt;&lt;br&gt;
and download it.&lt;/p&gt;

&lt;p&gt;After a few minutes, you can run the following command to check that your container was downloaded &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo docker images&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and you should see&lt;/p&gt;

&lt;p&gt;kernel-builder-515:latest   9f311ec05f16        580MB          147MB    U&lt;br&gt;&lt;br&gt;
ubuntu:16.04                1f1a2d56de1d        195MB         46.5MB    U   &lt;/p&gt;

&lt;p&gt;I always favor LTS (Long Term Support) versions like 16.04, because they guarantee library longevity and compilation tool stability, which is critical to avoid linking errors when generating &lt;code&gt;vmlinux&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;See the difference here: ubuntu:16.04 is the raw image we just downloaded, while kernel-builder-515 represents the kernel 5.15 image that I customized to include all the necessary compilation tools. We will now cover this customization step using the Dockerfile.&lt;/p&gt;

&lt;p&gt;To customize the downloaded Docker container, we use a &lt;code&gt;Dockerfile&lt;/code&gt;, here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;### Example for kernel 4.7 (based on Ubuntu 16.04 - Xenial)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:16.04&lt;/span&gt;

&lt;span class="c"&gt;### Install compilation dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    build-essential &lt;span class="se"&gt;\
&lt;/span&gt;    libncurses5-dev &lt;span class="se"&gt;\
&lt;/span&gt;    bison &lt;span class="se"&gt;\
&lt;/span&gt;    flex &lt;span class="se"&gt;\
&lt;/span&gt;    libssl-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libelf-dev &lt;span class="se"&gt;\
&lt;/span&gt;    gcc-5 g++-5 &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; update-alternatives &lt;span class="nt"&gt;--install&lt;/span&gt; /usr/bin/gcc gcc /usr/bin/gcc-5 100

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/linux&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a personal container version, just run the command:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo docker build -t my-ubuntu:16.04 .&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;if we launch sudo docker images, you should see  the following result&lt;/p&gt;

&lt;p&gt;kernel-builder-515:latest   9f311ec05f16        580MB          147MB    U&lt;br&gt;&lt;br&gt;
my-ubuntu:16.04             3aa5b81c120f        822MB          188MB    U&lt;br&gt;&lt;br&gt;
ubuntu:16.04                1f1a2d56de1d        195MB         46.5MB    U   &lt;/p&gt;

&lt;p&gt;You can find other Dockerfile examples at &lt;a href="https://github.com/ddupard/low-level-security-research" rel="noopener noreferrer"&gt;https://github.com/ddupard/low-level-security-research&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have followed all previous steps, you should be able to compile without issues by running these commands in a shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; ~/Desktop/KERNEL/4.7:/build &lt;span class="se"&gt;\&lt;/span&gt;
  my-ubuntu:16.04

make x86_64_defconfig

scripts/config &lt;span class="nt"&gt;--enable&lt;/span&gt; CONFIG_DEBUG_INFO
scripts/config &lt;span class="nt"&gt;--disable&lt;/span&gt; CONFIG_DEBUG_INFO_REDUCED
scripts/config &lt;span class="nt"&gt;--enable&lt;/span&gt; CONFIG_GDB_SCRIPTS
scripts/config &lt;span class="nt"&gt;--enable&lt;/span&gt; CONFIG_DEBUG_KERNEL
scripts/config &lt;span class="nt"&gt;--disable&lt;/span&gt; CONFIG_RANDOMIZE_BASE

make olddefconfig
make scripts_gdb

make &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;et voila&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa52f4xs6l1dpoifdhshi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa52f4xs6l1dpoifdhshi.png" alt="kernel compilation" width="799" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Creating the runtime
&lt;/h2&gt;

&lt;p&gt;This step consists of two parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieving and compiling BusyBox.&lt;/li&gt;
&lt;li&gt;Creating the &lt;code&gt;initramfs.cpio.gz&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike a complete Linux distribution that weighs gigabytes, BusyBox bundles essential utilities (ls, cat, sh, etc.) into a single binary executable.&lt;/p&gt;

&lt;p&gt;We start by creating a shell script (&lt;code&gt;build_busybox.sh&lt;/code&gt;) to download the BusyBox sources and compile them within Docker using &lt;code&gt;my-ubuntu:16.04&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;BUSYBOX_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1.36.1"&lt;/span&gt;
&lt;span class="nv"&gt;BUSYBOX_TAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"busybox-&lt;/span&gt;&lt;span class="nv"&gt;$BUSYBOX_VERSION&lt;/span&gt;&lt;span class="s2"&gt;.tar.bz2"&lt;/span&gt;
&lt;span class="nv"&gt;BUILD_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/busybox_build"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BUSYBOX_TAR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Downloading BusyBox &lt;/span&gt;&lt;span class="nv"&gt;$BUSYBOX_VERSION&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
    wget &lt;span class="s2"&gt;"https://busybox.net/downloads/&lt;/span&gt;&lt;span class="nv"&gt;$BUSYBOX_TAR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;tar &lt;/span&gt;xvf &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BUSYBOX_TAR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"busybox-&lt;/span&gt;&lt;span class="nv"&gt;$BUSYBOX_VERSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

make defconfig
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/.*CONFIG_STATIC.*/CONFIG_STATIC=y/'&lt;/span&gt; .config

&lt;span class="c"&gt;### 4. Compilation&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Compilation of BusyBox..."&lt;/span&gt;
make &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
make &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;CONFIG_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BUILD_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"BusyBox compiled in : &lt;/span&gt;&lt;span class="nv"&gt;$BUILD_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then we launch the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:/build &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; /build &lt;span class="se"&gt;\&lt;/span&gt;
  my-ubuntu:16.04 &lt;span class="se"&gt;\&lt;/span&gt;
  /bin/bash ./build_busybox.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the compilation fails with the following message indicating that wget and other executables are missing&lt;/p&gt;

&lt;p&gt;sudo docker run -it \&lt;br&gt;
  -v "$(pwd)":/build \&lt;br&gt;
  -w /build \&lt;br&gt;
  my-ubuntu:16.04 \&lt;br&gt;
  /bin/bash ./build_busybox.sh&lt;br&gt;
Téléchargement de BusyBox 1.36.1...&lt;br&gt;
./build_busybox.sh: line 11: wget: command not found&lt;br&gt;
tar: busybox-1.36.1.tar.bz2: Cannot open: No such file or directory&lt;br&gt;
tar: Error is not recoverable: exiting now&lt;/p&gt;

&lt;p&gt;so we need to modify the Dockerfile in order to include these new executables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:16.04&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    build-essential &lt;span class="se"&gt;\
&lt;/span&gt;    gcc &lt;span class="se"&gt;\
&lt;/span&gt;    make &lt;span class="se"&gt;\
&lt;/span&gt;    libncurses5-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libssl-dev &lt;span class="se"&gt;\
&lt;/span&gt;    bc &lt;span class="se"&gt;\
&lt;/span&gt;    bison &lt;span class="se"&gt;\
&lt;/span&gt;    flex &lt;span class="se"&gt;\
&lt;/span&gt;    nano &lt;span class="se"&gt;\
&lt;/span&gt;    git &lt;span class="se"&gt;\
&lt;/span&gt;    cpio &lt;span class="se"&gt;\
&lt;/span&gt;    openssh-client &lt;span class="se"&gt;\
&lt;/span&gt;    wget &lt;span class="se"&gt;\
&lt;/span&gt;    bzip2 &lt;span class="se"&gt;\
&lt;/span&gt;    ca-certificates &lt;span class="se"&gt;\
&lt;/span&gt;    linux-headers-generic &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;


&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /opt&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;git clone https://github.com/radareorg/radare2 &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; radare2/sys/install.sh &lt;span class="nt"&gt;--install&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; radare2

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now we can recreate the container using &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo docker build -t my-ubuntu:16.04 .&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;then we rebuild busybox with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:/build &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; /build &lt;span class="se"&gt;\&lt;/span&gt;
  my-ubuntu:16.04 &lt;span class="se"&gt;\&lt;/span&gt;
  /bin/bash ./build_busybox.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F694oirrooyyeo53sgqbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F694oirrooyyeo53sgqbe.png" alt=" " width="799" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;however the compilation process wil fail with the following message&lt;/p&gt;

&lt;p&gt;CC      miscutils/mt.o&lt;br&gt;
  CC      miscutils/nandwrite.o&lt;br&gt;
  CC      miscutils/partprobe.o&lt;br&gt;
  CC      miscutils/raidautorun.o&lt;br&gt;
  CC      miscutils/readahead.o&lt;br&gt;
  CC      miscutils/runlevel.o&lt;br&gt;
  CC      miscutils/rx.o&lt;br&gt;
  CC      miscutils/seedrng.o&lt;br&gt;
miscutils/seedrng.c:45:24: fatal error: sys/random.h: No such file or directory&lt;/p&gt;

&lt;p&gt;it's because you are compiling a recent version of BusyBox with an old Ubuntu 16.04 base.&lt;br&gt;
in order to solve our problem, we will launch the following commands&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo docker ps -a&lt;br&gt;
in order to get the list of the last docker commands launched&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CONTAINER ID&lt;/th&gt;
&lt;th&gt;IMAGE&lt;/th&gt;
&lt;th&gt;COMMAND&lt;/th&gt;
&lt;th&gt;CREATED&lt;/th&gt;
&lt;th&gt;STATUS&lt;/th&gt;
&lt;th&gt;PORTS NAMES&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;49c7144e4dbb&lt;/td&gt;
&lt;td&gt;my-ubuntu:16.04&lt;/td&gt;
&lt;td&gt;"/bin/bash ./build_b…"&lt;/td&gt;
&lt;td&gt;13 minutes ago&lt;/td&gt;
&lt;td&gt;Exited (0) 10 minutes ago&lt;/td&gt;
&lt;td&gt;mystifying_mayer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;eb9d3d19f3a0&lt;/td&gt;
&lt;td&gt;58aacbfbda6f&lt;/td&gt;
&lt;td&gt;"/bin/bash ./build_b…"&lt;/td&gt;
&lt;td&gt;23 minutes ago&lt;/td&gt;
&lt;td&gt;Exited (0) 23 minutes ago&lt;/td&gt;
&lt;td&gt;wonderful_jemison&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;then&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker start 49c7144e4dbb
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; 49c7144e4dbb /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to restart the docker environment  (root@49c7144e4dbb:/build#)&lt;br&gt;
then the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /build/busybox-1.36.1
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/CONFIG_SEEDRNG=y/CONFIG_SEEDRNG=n/'&lt;/span&gt; .config

make clean
make &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;compilation should restart and go to the end.&lt;/p&gt;

&lt;p&gt;then we launch the following command to make the install&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;make install CONFIG_PREFIX="$(pwd)/../busybox_build"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;at the end a new directory should appear &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fyxsmkse0un5knc5tjd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fyxsmkse0un5knc5tjd.png" alt=" " width="736" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that BusyBox has copiled, it's time to create initramfs.cpio.gz that sets up the file structure (&lt;code&gt;/proc&lt;/code&gt;, &lt;code&gt;/sys&lt;/code&gt;, etc.) &lt;/p&gt;

&lt;p&gt;we are going to create and lauch a new shell script (create_initramfs.sh)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;BUILD_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/busybox_build"&lt;/span&gt;
&lt;span class="nv"&gt;ROOTFS_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/initramfs_staging"&lt;/span&gt;

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOTFS_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOTFS_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BUILD_DIR&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOTFS_DIR&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOTFS_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; proc sys dev etc/init.d

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; init
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "--- Système démarré avec succès ---"
exec /bin/sh
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x init

find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-print0&lt;/span&gt; | cpio &lt;span class="nt"&gt;--null&lt;/span&gt; &lt;span class="nt"&gt;-ov&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;newc | &lt;span class="nb"&gt;gzip&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ../initramfs.cpio.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;at the end of its execution, we should see something like &lt;br&gt;
./bin/mknod&lt;br&gt;
./bin/more&lt;br&gt;
./bin/zcat&lt;br&gt;
./bin/pidof&lt;br&gt;
./bin/egrep&lt;br&gt;
./bin/watch&lt;br&gt;
./bin/link&lt;br&gt;
./bin/pwd&lt;br&gt;
./bin/dd&lt;br&gt;
./bin/netstat&lt;br&gt;
./bin/fgrep&lt;br&gt;
./bin/stty&lt;br&gt;
./bin/mt&lt;br&gt;
./bin/gunzip&lt;br&gt;
./proc&lt;br&gt;
./etc&lt;br&gt;
./etc/init.d&lt;br&gt;
./init&lt;br&gt;
5556 blocks&lt;/p&gt;

&lt;p&gt;and a new file in the root directory (initramfs.cpio.gz)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyg3s2h7jf12x4uze6p9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyg3s2h7jf12x4uze6p9.png" alt=" " width="736" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;to check that everything is fine , we are going to launch the VM using the following command&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;qemu-system-x86_64 \&lt;br&gt;
  -kernel ./4.7/arch/x86/boot/bzImage \&lt;br&gt;
  -initrd ./initramfs.cpio.gz \&lt;br&gt;
  -append "console=ttyS0 nokaslr" \&lt;br&gt;
  -nographic &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and something like below should appear&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hxpzfg0zra09ijqy444.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hxpzfg0zra09ijqy444.png" alt=" " width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if it happens , congrats your environment is working now&lt;/p&gt;
&lt;h2&gt;
  
  
  3) Debugging setup
&lt;/h2&gt;

&lt;p&gt;To debug the kernel, the base tool is GDB, but it isn't very user-friendly. The idea here is to use VS Code's overlay for GDB.&lt;/p&gt;

&lt;p&gt;First, ensure you compile with debug options in your &lt;code&gt;compile_4.7.sh&lt;/code&gt; script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./scripts/config &lt;span class="nt"&gt;--enable&lt;/span&gt; CONFIG_DEBUG_INFO
./scripts/config &lt;span class="nt"&gt;--disable&lt;/span&gt; CONFIG_DEBUG_INFO_REDUCED
./scripts/config &lt;span class="nt"&gt;--enable&lt;/span&gt; CONFIG_GDB_SCRIPTS
./scripts/config &lt;span class="nt"&gt;--enable&lt;/span&gt; CONFIG_DEBUG_KERNEL
./scripts/config &lt;span class="nt"&gt;--disable&lt;/span&gt; CONFIG_RANDOMIZE_BASE

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;file ./4.7/vmlinux&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(You should see a line containing "with debug_info")&lt;/p&gt;

&lt;p&gt;Then, launch QEMU with the &lt;code&gt;-s&lt;/code&gt; and &lt;code&gt;-S&lt;/code&gt; options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-s&lt;/code&gt;: Opens a GDB server on &lt;code&gt;tcp::1234&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-S&lt;/code&gt;: Freezes QEMU at the first instruction.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;qemu-system-x86_64 \&lt;br&gt;
  -kernel ./4.7/arch/x86/boot/bzImage \&lt;br&gt;
  -initrd ./initramfs.cpio.gz \&lt;br&gt;
  -append "console=ttyS0 nokaslr" \&lt;br&gt;
  -nographic \&lt;br&gt;
  -s -S&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In VS Code, install the &lt;strong&gt;C/C++&lt;/strong&gt; extension from Microsoft and create a &lt;code&gt;.vscode/launch.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(gdb) Attacher au Kernel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cppdbg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/4.7/vmlinux"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"miDebuggerServerAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost:1234"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"miDebuggerPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin/gdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"setupCommands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-enable-pretty-printing"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Debugging Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Launch QEMU (using your script with &lt;code&gt;-s -S&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;In VS Code, go to the 4.7 directory and launch the "Debug Kernel LKM" configuration.&lt;/li&gt;
&lt;li&gt;This triggers the kernel to start. You can now set breakpoints, view registers, and use the debug console to launch commands like the following&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;-exec info functions&lt;/code&gt;&lt;br&gt;
&lt;code&gt;-exec p/x $rax&lt;/code&gt;&lt;br&gt;
&lt;code&gt;-exec monitor xp/512gx  0x4786000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsnsf7tq0aehypb1i6l3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsnsf7tq0aehypb1i6l3.png" alt=" " width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: If you load an LKM, you must load the symbol file and tell GDB where the source files are located using:&lt;/em&gt;&lt;br&gt;
&lt;code&gt;-exec add-symbol-file /path/to/my_attack.ko ...&lt;/code&gt;&lt;br&gt;
&lt;code&gt;-exec set substitute-path ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Happy kernel debugging!&lt;/p&gt;


&lt;h2&gt;
  
  
  Appendix: Automation Script
&lt;/h2&gt;

&lt;p&gt;To make the environment setup more efficient, I use a script (&lt;code&gt;run_qemu.sh&lt;/code&gt;) to quickly switch between different kernel versions and automate the LKM injection process for the 5.15 LTS kernel.&lt;/p&gt;

&lt;p&gt;You can save the following code into a file named &lt;code&gt;run_qemu.sh&lt;/code&gt; in your &lt;code&gt;~/Desktop/KERNEL&lt;/code&gt; directory. Make sure to give it execution permissions with &lt;code&gt;chmod +x run_qemu.sh&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# This script runs on the host (Ubuntu) in ~/Desktop/KERNEL&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Desktop/KERNEL"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"-------------------------------------------------------"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  COGNITIVE FIREWALL LAB - TEST ENVIRONMENT"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"-------------------------------------------------------"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Select the kernel version to test:"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"1) Kernel 4.7  (Dirty COW vulnerable)"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"2) Kernel 4.8  (Intro XDP)"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"3) Kernel 4.9  (Dirty COW patched)"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"4) Kernel 5.15 (LTS)"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"q) Quit"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"-------------------------------------------------------"&lt;/span&gt;

&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Your choice [1-4] : "&lt;/span&gt; choice

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;$choice&lt;/span&gt; &lt;span class="k"&gt;in
    &lt;/span&gt;1&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"4.7"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;KERNEL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./4.7/arch/x86/boot/bzImage"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    2&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"4.8"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;KERNEL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./4.8/arch/x86/boot/bzImage"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    3&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"4.9"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;KERNEL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./4.9/arch/x86/boot/bzImage"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;        
    4&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"5.15"&lt;/span&gt;
        &lt;span class="nv"&gt;KERNEL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./5.15/arch/x86/boot/bzImage"&lt;/span&gt;
        &lt;span class="nv"&gt;LKM2_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./lkm/poc/my_attack.ko"&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LKM2_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Building initramfs for Kernel 5.15..."&lt;/span&gt;
            &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .initramfs_root
            &lt;span class="nb"&gt;cd&lt;/span&gt; .initramfs_root
            zcat ../initramfs.cpio.gz | cpio &lt;span class="nt"&gt;-idmv&lt;/span&gt; &amp;amp;&amp;gt;/dev/null
            &lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="s2"&gt;"../&lt;/span&gt;&lt;span class="nv"&gt;$LKM2_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

            &lt;span class="c"&gt;# Automatic LKM injection script&lt;/span&gt;
            &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' &amp;gt; init
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev 2&amp;gt;/dev/null
if [ -f /my_attack.ko ]; then insmod /my_attack.ko; fi
exec /bin/sh
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;            &lt;span class="nb"&gt;chmod&lt;/span&gt; +x init
            find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-print0&lt;/span&gt; | cpio &lt;span class="nt"&gt;--null&lt;/span&gt; &lt;span class="nt"&gt;-ov&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;newc 2&amp;gt;/dev/null | &lt;span class="nb"&gt;gzip&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ../initramfs.cpio.gz
            &lt;span class="nb"&gt;cd&lt;/span&gt; ..
            &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; .initramfs_root
        &lt;span class="k"&gt;fi
        &lt;/span&gt;qemu-system-x86_64 &lt;span class="nt"&gt;-kernel&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-initrd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Desktop/KERNEL/initramfs.cpio.gz"&lt;/span&gt; &lt;span class="nt"&gt;-nographic&lt;/span&gt; &lt;span class="nt"&gt;-append&lt;/span&gt; &lt;span class="s2"&gt;"console=ttyS0 loglevel=7 nosmep nosmap nokaslr"&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt;
        &lt;span class="nb"&gt;exit &lt;/span&gt;0
        &lt;span class="p"&gt;;;&lt;/span&gt;
    q&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0 &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Invalid choice"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

&lt;span class="c"&gt;# Launch QEMU for versions 1, 2, 3&lt;/span&gt;
qemu-system-x86_64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-kernel&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-initrd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Desktop/KERNEL/initramfs.cpio.gz"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-nographic&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-append&lt;/span&gt; &lt;span class="s2"&gt;"console=ttyS0 nokaslr loglevel=7"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>linux</category>
      <category>kernel</category>
      <category>security</category>
    </item>
  </channel>
</rss>
