Art of Shellcoding: Cracking Eggs with EggHunters
A restored 2018 article on Linux x86 egghunter design, memory scanning, EFAULT handling, SCASD comparisons and staged payload discovery.
Shellcode Research Nipun Jaswal todayFebruary 6, 2018 3
Legacy research restoration. Originally published on 6 February 2018 as part of the SecurityTube Linux Assembly Expert programme under student ID SLAE-1080. The original technical sequence, screenshots, source references and publication date have been preserved from the Blogger Takeout archive.

This fourth article in the Art of Shellcoding series explores the design of a custom encoder for a compact Linux x86 /bin/sh payload. The objective was to create a reversible multi-stage byte transformation, implement its decoder in assembly, and verify every decoding step in GDB rather than treating the result as a black box.
The source payload used in the exercise was a 25-byte stack-based execve implementation. The original source remains referenced in the SLAE assignment repository.
The encoder transforms every byte through four operations:
0xAA0xCF131The decoder reverses those operations in the opposite order:
1310xCF0xAAOriginal Python encoder: view the archived GitHub Gist.

The assembly decoder removes the offset, performs the NOT operation, and applies the two XOR operations to every encoded byte. After processing all 25 bytes, execution transfers to the reconstructed payload.
Original assembly decoder: view the archived GitHub Gist.
The assembled decoder and encoded payload were then placed inside a small C execution wrapper for controlled testing.
Original C wrapper: view the archived GitHub Gist.

The debugger walkthrough followed the first encoded byte through each inverse transformation. The encoded buffer begins with 0x2e, which ultimately returns to the original 0x31 byte.

Subtracting decimal 131 changes the encoded byte from 0x2e to 0xab.

The bitwise NOT operation changes 0xab to 0x54.

XOR with 0xCF produces 0x9b; XOR with 0xAA restores the original 0x31 byte.

The loop repeats for the remaining 24 bytes. Immediately before transferring execution, the complete original payload is visible in memory.

The important result was not the choice of constants. The exercise demonstrated how to design a reversible transformation, implement both sides consistently, account for payload length and control flow, and prove correctness byte by byte.
It also illustrates a persistent trade-off in payload engineering: encoding may alter byte patterns and avoid selected bad characters, but the decoder increases size and introduces its own recognisable structure. Simple encoding should not be confused with reliable modern evasion.
Art of Shellcoding series
← Previous: EggHunters · Series hub · Next: Add User Payload →
This article documents historical 32-bit Linux exploit-development research and tooling. Modern processors, compilers and operating systems commonly introduce protections that change build and execution behaviour. The work is retained for controlled labs, defensive understanding and the historical research record.
Authorisation notice: Test only on systems you own or are explicitly authorised to assess.
Written by: Nipun Jaswal
Shellcode Research Nipun Jaswal
A restored 2018 article on Linux x86 egghunter design, memory scanning, EFAULT handling, SCASD comparisons and staged payload discovery.
Copyright 2026 NIPUNJASWAL.COM