- This project implements a low-level side channel based on AVX instructions to detect the presence of Address Space Layout Randomization (ASLR) in hardened Linux environments. It performs memory loading on a known libc symbol (open() in libc) and measures access latency using RDTSCP to infer the state of the memory layout. Fast access indicates a static layout where ASLR is disabled or bypassed, while slow access or a SIGSEGV suggests randomized or unmapped memory. The system utilizes advanced CPU features—AVX, AVX2, TSX, RDTSC, and RDTSCP—to construct a timing-based oracle that operates without direct memory inspection. Signal handling via sigsetjmp/siglongjmp ensures recovery from illegal instructions and segmentation faults without terminating the process. Execution is isolated using fork(), allowing the probing logic to run in a child process while the parent monitors its state via wait() and syscall-level introspection. This implementation transforms timing analysis into a deterministic side-channel framework capable of detecting ASLR through pure architectural feedback, without relying on brute-force techniques or binary parsing.
- This technique detects the presence of Address Space Layout Randomization (ASLR) by performing AVX-based memory loads on known function addresses—such as open() in libc—and measuring access latency using RDTSCP. The number of CPU cycles required for access serves as a timing oracle: fast access indicates a mapped address, while slower access suggests randomized or unmapped memory. To enhance detection accuracy, optional SIGSEGV handling is implemented to catch illegal memory accesses, providing an additional side-channel signal. The method leverages modern CPU features—AVX, AVX2, TSX, RDTSC, and RDTSCP—to construct a precise timing-based side channel that reveals memory layout randomization patterns. This approach demonstrates how low-level architectural feedback can be used to bypass ASLR protections, exposing potential vulnerabilities in system-level security mechanisms.
- In this step, the script checks the system's support for CPU features required for AVX-based timing attacks, including AVX, AVX2, TSX, RDTSC, and RDTSCP. This ensures the environment is capable of performing precise memory access timing for ASLR detection :
- Intel documentation :
- Code :
__asm__ volatile
(
"mov $0x7, %%eax\n\t" //set CPUID leaf to 0x7
"mov $0x0, %%ecx\n\t" //set subleaf to 0x0
"cpuid\n\t" //execute CPUID
: "=a"(eaxV),
"=b"(ebxV),
"=c"(ecxV), //cpuid output registers: EAX, EBX, ECX, EDX
"=d"(edxV)
:
: "memory" //prevent instruction reordering around CPUID
);
if (ebxV & (1u << 5)) //check if bit 5 in EBX is set (AVX2 support)
{
printf("\e[0;34m[+] AVX2 Supported.\e[0m\n"); //if bit 5 in EBX is set → AVX2 is supported
}
else
{
printf("\e[0;31m[-] AVX2 Not Supported.\e[0m\n"); // if bit 5 in EBX is not set → AVX2 not supported
}
- Intel documentation :
- Code :
- Intel documentation :
style="display:block; width:600px; height:auto; border:1px solid #ccc; border-radius:5px; margin:10px auto 10px 40px;">
- Code :
- Intel documentation :
- Code :
# gcc avx.c -o AVX # ./AVX
[+] Fork CALL success. [+] Child PID : 3113 [+] Running PID : 3112 [+] Address Varaible Status : 0x7ffea48dec7c [+] Parent PID : 3112 (dec : 3112) [+] PID : 3113 [+] CPU Supported AVX + OSXSAVE . [+] Check Support RDTSC / RDTSCP... +-----------------------------------------------------------------------------+ | EAX : 0x406e3 CPUID Function 1 | Dec : 263907 | Bin : 0000 0000 0000 0100 0000 0110 1110 0011 +-----------------------------------------------------------------------------+ [+] RDTSC Supported (Bit shift 4 EDX). [+] RDTSCP Supported (Bit shift 27 EDX). [+] Check Support TSX (Transactional Synchronization Extensions) +-----------------------------------------------------------------------------+ [+] Arg 1 (CPUID -> EAX = 07H): | EAX : 0x7 EAX = 07H CPUID | Dec : 7 ....
File: avx.c — Size: 18,4 KB — Lines: 655
#include <immintrin.h>
#include <signal.h>
#include <setjmp.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/wait.h>
#define D_C 150
#define B_F 32
volatile sig_atomic_t f = 0;
uint32_t eaxV;
uint32_t ecxV;
uint32_t ebxV;
uint32_t edxV;
sigjmp_buf b;
void showBit(unsigned int n)
{
for (int i = 31; i >= 0; i--)
{
printf("%d", (n >> i) & 1);
if (i % 4 == 0)
{
printf(" ");
}
}
printf("\n");
}
void sH(int sig)
{
const char *mes7 = "\e[0;31m[-] Segfault/Illegal instruction caught\e[0m\n";
size_t len7 = strlen(mes7);
__asm__ volatile
(
"mov $0x1, %%rax\n\t"
"mov $0x1, %%rdi\n\t"
"mov %[mes7], %%rsi\n\t"
"mov %[len7], %%rdx\n\t"
"syscall\n\t"
:
: [mes7] "r" (mes7),
[len7] "r" (len7)
: "rcx",
"r11",
"memory",
"rax",
"rdi",
"rsi",
"rdx"
);
__asm__ volatile
(
"add $0x1, %[f]\n\t"
: [f] "+r" (f)
:
:
);
siglongjmp(b,
1);
}
static void avx(void)
{
uint64_t start,end;
unsigned int time=0;
uint8_t tmp[B_F];
pid_t pid;
long r;
pid_t tid;
long v;
__asm__ volatile
(
"syscall"
: "=a"(r)
: "a"(0x27)
: "rcx",
"r11",
"memory"
);
pid = (pid_t)r;
if (pid == 0)
{
printf("\e[0;31m[-] Error Get PID !\e[0m\n");
__asm__ volatile
(
"xor %%rdi, %%rdi\n\t"
"mov $0x3C, %%rax\n\t"
"syscall\n\t"
:
:
: "rcx",
"r11",
"memory",
"rax",
"rdi"
);
}
__asm__ volatile
(
"add $0x1, %[eaxV]\n\t"
:[eaxV] "+r" (eaxV)
:
:
);
__asm__ volatile
(
"cpuid"
: "=a"(eaxV),
"=b"(ebxV),
"=c"(ecxV),
"=d"(edxV)
: "a"(eaxV)
);
printf("\e[0;32m[+] PID : %d\e[0m\n", pid);
if (ecxV & (1 << 28))
{
if (!(ecxV & (1U << 27)))
{
printf("\e[0;31m[-] OSXSAVE not supported (kernel/OS may not save YMM)\e[0m\n");
__asm__ volatile
(
"xor %%rdi, %%rdi\n\t"
"mov $0x3C, %%rax\n\t"
"syscall\n\t"
:
:
: "rcx",
"r11",
"memory",
"rax",
"rdi"
);
}
else
{
printf("[+] CPU Supported AVX + OSXSAVE . \e[0m\n");
printf("[+] Check Support RDTSC / RDTSCP...\e[0m\n");
printf("\e[0;35m +-----------------------------------------------------------------------------+\n");
printf("\e[0;37m| EAX : 0x%lx CPUID Function 1 \e[0m\n", eaxV);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)eaxV);
printf("\e[0;37m| Bin : ");
showBit(eaxV);
printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
__asm__ volatile
(
"cpuid"
: "=a"(eaxV),
"=b"(ebxV),
"=c"(ecxV),
"=d"(edxV)
: "a"(1)
);
int hT = (edxV & (1u << 4)) ? 1 : 0;
__asm__ volatile
(
"cpuid"
: "=a"(eaxV),
"=b"(ebxV),
"=c"(ecxV),
"=d"(edxV)
: "a"(0x80000001)
);
int rdT = (edxV & (1u << 27)) ? 1 : 0;
if (hT)
{
printf("\e[0;34m[+] RDTSC Supported (Bit shift 4 EDX).\e[0m\n");
if (rdT)
{
printf("\e[0;34m[+] RDTSCP Supported (Bit shift 27 EDX).\e[0m\n");
}
else
{
printf("\e[0;31m[-] RDTSCP Not Supported.\e[0m\n");
}
}
else
{
printf("\e[0;31m[-] RDTSC / RDTSCP Not Supported, Exit...\e[0m\n");
unsigned int a = 0xBA;
printf(" +-----------------------------------------------------------------------------+\e[0m\n");
printf("\e[0;37m| RAX : 0x%lx sys_gettid \e[0m\n", 0xBA);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0xBA);
printf("\e[0;37m| Bin : ");
showBit(a);
printf(" +-----------------------------------------------------------------------------+\e[0m\n");
__asm__ volatile
(
"syscall"
: "=a" (v)
: "a" (0xBA)
: "rcx",
"r11",
"memory"
);
tid = (pid_t) v;
if (tid == 0)
{
printf("\e[0;31m[-] Error Get TID value !\e[0m\n");
__asm__ volatile
(
"xor %%rdi, %%rdi\n\t"
"mov $0x3C, %%rax\n\t"
"syscall\n\t"
:
:
: "rcx",
"r11",
"memory",
"rax",
"rdi"
);
}
const char *mes2 ="\e[0;31m[-] Error sys_tgkill return value != 0\e[0m\n";
size_t len2 = strlen(mes2);
printf("\e[0;32m[+] TID : %d\e[0m\n", tid);
unsigned int g = (unsigned int)0xBA;
printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
printf("\e[0;33m[+] Arg 1 (sys_tgkill):\e[0m\n");
printf("\e[0;37m| RAX : 0x%lx syscall \e[0m\n", 0xEA);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0xEA);
printf("\e[0;37m| Bin : ");
showBit(g);
unsigned int g2 = (int)pid;
printf("\e[0;33m[+] Arg 2 (PID -> %d):\e[0m\n", pid);
printf("\e[0;37m| RDI : 0x%lx sys_tgkill \e[0m\n", pid);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)pid);
printf("\e[0;37m| Bin : ");
showBit(g2);
unsigned int g3 = (int)tid;
printf("\e[0;33m[+] Arg 3 (TID -> %d):\e[0m\n", tid);
printf("\e[0;37m| RSI : 0x%lx sys_tgkill \e[0m\n", tid);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)tid);
printf("\e[0;37m| Bin : ");
showBit(g3);
unsigned int g4 = (unsigned int)0x9;
printf("\e[0;33m[+] Arg 4 :\e[0m\n");
printf("\e[0;37m| RDX : 0x%lx SIGKILL \e[0m \n", 0x9);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x9);
printf("\e[0;37m| Bin : ");
showBit(g4);
printf(" \e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
__asm__ volatile
(
"mov $0xEA, %%rax\n\t"
"mov %q[pid], %%rdi\n\t"
"mov %q[tid], %%rsi\n\t"
"mov $0x9, %%rdx\n\t"
"syscall\n\t"
"cmp $0x0, %%rax\n\t"
"je .d\n\t"
".d:\n\t"
"mov $0x1, %%rax\n\t"
"mov $0x1, %%rdi\n\t"
"mov %[mes2], %%rsi\n\t"
"mov %[len2], %%rdx\n\t"
"mov $0x0, %%rdi\n\t"
"mov $0x3C, %%rax\n\t"
".fD:\n\t"
:
: [pid] "r" (pid),
[tid] "r" (tid),
[mes2] "r" (mes2),
[len2] "r" (len2)
:"rax",
"rdi",
"rsi",
"rdx"
);
}
printf("\e[0;33m[+] Check Support TSX (Transactional Synchronization Extensions)\e[0m\n");
unsigned int g6 = (unsigned int)0x7;
printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
printf("\e[0;33m[+] Arg 1 (CPUID -> EAX = 07H): \e[0m\n");
printf("\e[0;37m| EAX : 0x%lx EAX = 07H CPUID \e[0m\n", 0x7);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x7);
printf("\e[0;37m| Bin : ");
showBit(g6);
unsigned int g7= (unsigned int)0x0;
printf("\e[0;33m[+] Arg 2 (CPUID -> ECX=0H): \e[0m\n");
printf("\e[0;37m| ECX : 0x%lx ECX=0H CPUID \e[0m\n", 0x0);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x0);
printf("\e[0;37m| Bin : ");
showBit(g7);
__asm__ volatile
(
"mov $0x7, %%eax\n\t"
"mov $0x0, %%ecx\n\t"
"cpuid\n\t"
: "=a"(eaxV),
"=b"(ebxV),
"=c"(ecxV),
"=d"(edxV)
: "a"(eaxV)
);
unsigned int g8= (unsigned int)0x7;
printf("\e[0;33m[+] Result bit EBX \"TSX\": \e[0m\n");
printf("\e[0;37m| EBX : 0x%lx Ebx result \e[0m \n", ebxV);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)ebxV);
printf("\e[0;37m| Bin : ");
showBit(g8);
printf(" \e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
if (ebxV & (1 << 11))
{
printf("[+] TSX/RTM Supported.\e[0m\n");
}
else
{
printf("\e[0;31m[-] TSX/RTM Not Supported\e[0m\n");
}
printf("\e[0;34m[+] Check Support AVX2...\e[0m\n");
__asm__ volatile
(
"mov $0x7, %%eax\n\t"
"mov $0x0, %%ecx\n\t"
"cpuid\n\t"
: "=a"(eaxV),
"=b"(ebxV),
"=c"(ecxV),
"=d"(edxV)
:
: "memory"
);
if (ebxV & (1u << 5))
{
printf("\e[0;34m[+] AVX2 Supported.\e[0m\n");
}
else
{
printf("\e[0;31m[-] AVX2 Not Supported.\e[0m\n");
}
goto run;
}
}
else
{
printf("\e[0;31m[-] CPU Not Supported AVX, exit...\e[0m\n");
unsigned int g9 = (unsigned int)0x3C;
printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
printf("\e[0;33m[+] Arg 1 (exit): \e[0m\n");
printf("\e[0;37m| RAX : 0x%lx exit syscall \e[0m\n", 0x3C);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x3C);
printf("\e[0;37m| Bin : ");
showBit(g9);
unsigned int g10 = (unsigned int)0x0;
printf("\e[0;33m[+] Arg 2 (exit): \e[0m\n");
printf("\e[0;37m| RDI : 0x%lx \e[0m\n", 0x0);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x0);
printf("\e[0;37m| Bin : ");
showBit(g10);
printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
__asm__ volatile
(
"xor %%rdi, %%rdi\n\t"
"mov $0x3C, %%rax\n\t"
"syscall"
:
:
:"rax",
"rdi"
);
}
run :
void *ptr = (void*) &open;
if (ptr == NULL)
{
printf("\e[0;31m[-] Error get Address : NULL pointer !\e[0m\n");
printf("\e[0;31m[-] Kill Proccess...\e[0m\n");
printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
unsigned int g11 = (unsigned int)0x3E;
printf("\e[0;33m[+] Arg 1 (kill): \e[0m\n");
printf("\e[0;37m| RAX : 0x%lx exit syscall \e[0m\n", 0x3E);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x3E);
printf("\e[0;37m| Bin : ");
showBit(g11);
unsigned int g12 = (unsigned int)pid;
printf("\e[0;33m[+] Arg 2 (PID -> %d): \e[0m\n", pid);
printf("\e[0;37m| RDI : 0x%lx PID \e[0m\n", pid);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)pid);
printf("\e[0;37m| Bin : ");
showBit(g12);
unsigned int g13 = 0x0;
printf("\e[0;33m[+] Arg 3 (sig -> 0x0): \e[0m\n");
printf("\e[0;37m| RSI : 0x%lx PID \e[0m\n", 0x0);
printf("\e[0;37m| Dec : %d\e[0m\n", (int)0x0);
printf("\e[0;37m| Bin : ");
showBit(g13);
printf("\e[0;35m+-----------------------------------------------------------------------------+\e[0m\n");
const char *mes6 = "\e[0;31m[-] Error kill process, exit group...\e[0m\n";
size_t len6 = (size_t)strlen(mes6);
__asm__ volatile
(
"mov $0x3E, %%rax\n\t"
"mov %[pid], %%rdi\n\t"
"mov $0x0, %%rsi\n\t"
"syscall\n\t"
"cmp $0x0, %%rax\n\t"
"je .1\n\t"
"1.\n\t"
"mov $0x1, %%rax\n\t"
"mov $0x1, %%rdi\n\t"
"mov %[mes6], %%rsi\n\t"
"mov %[len6], %%rdx\n\t"
"syscall\n\t"
"mov $0xE7, %%rax\n\t"
"mov $0x0, %%rdi\n\t"
"syscall\n\t"
".2:\n\t"
:
: [pid] "r" (pid),
[mes6] "r" (mes6),
[len6] "r" (len6)
:"rax",
"rdi",
"rsi",
"rdx",
"rcx",
"r11",
"memory"
);
}
int t = 0;
void* ptr2 = NULL;
__asm__ volatile
(
"lea %[var], %%rax\n\t"
"mov %%rax, %[value]\n\t"
: [value] "=r" (ptr2)
: [var] "m" (t)
: "rax"
);
if (ptr2 == NULL)
{
printf("[-] Error get address (flags Varaible)!\n");
}
printf("[+] flags Varaible time rdtscp address : %p\n", (void*)ptr2);
__asm__ volatile
(
"movl $0, %[f]\n\t"
: [f] "=m" (f)
:
:
);
if (sigsetjmp(b, 1) == 0)
{
printf("\e[0;34m[+] Address open() libc : %p\e[0m\n", (void *)ptr);
start = __rdtscp(&time);
__m256i ymm0 = _mm256_loadu_si256((__m256i*)ptr);
__m256i ymm1 = _mm256_setzero_si256();
ymm0 = _mm256_xor_si256(ymm0, ymm1);
_mm256_storeu_si256((__m256i*)tmp, ymm0);
end = __rdtscp(&time);
uint64_t result = end - start;
printf("\e[0;37m[+] Result CPU cycles: %llu\e[0m\n", (unsigned long long) result);
if ((uint64_t)result < D_C)
{
printf("\e[0;36m[+] Fast access, same address\e[0m\n");
}
else
{
printf("\e[0;31m[-] Slow access, ASLR or unmapped address\e[0m\n");
__asm__ volatile
(
"add $0x1, %[t]\n\t"
:[t] "+r" (t)
:
:
);
}
}
else
{
printf("\e[0;31m[-] Returned from signal handler — load faulted (segfault/illegal instr)\e[0m\n");
if (f==0)
{
__asm__ volatile
(
"add $0x1, %[f]\n\t"
:[f] "+r" (f)
:
:
);
}
}
printf("\e[0;35m[+] Result : =============================\e[0m\n");
if (t == 1 && f == 1)
{
printf("\e[0;33m[-] ASLR Detected by AVX-Based Timing Side Channel (rdtscp AND segfault)\e[0m\n");
}
else if (t == 1)
{
printf("\e[0;33m[-] ASLR Detected by AVX-Based Timing Side Channel (rdtscp)\e[0m\n");
}
else if (f == 1)
{
printf("\e[0;33m[-] ASLR Detected by AVX-Based Timing Side Channel (segfault)\e[0m\n");
}
else
{
printf("\e[0;36m[+] ASLR Not Detected by AVX-Based Timing Side Channel.\e[0m\n");
}
if (f == 0)
{
printf("\e[0;36m[+] No segfault/page-fault detected for load of open()\e[0m\n");
}
if (t == 0)
{
printf("\e[0;36m[+] No AVX-based timing side-channel detected (rdtscp)\e[0m\n");
}
}
void run()
{
pid_t p;
long y ;
__asm__ volatile
(
"syscall\n\t"
: "=a"(y)
: "a"(0x39)
: "rcx",
"r11",
"memory"
);
p = (pid_t) y;
if (p < 0)
{
printf("[-] Fork Failed !\n");
__asm__ volatile
(
"xor %%rdi, %%rdi\n\t"
"mov $0xE7, %%rax\n\t"
"syscall\n\t"
:
:
: "rcx",
"r11",
"memory",
"rax",
"rdi"
);
}
p = (pid_t) y;
if (p == 0)
{
printf("[+] Fork CALL success.\n");
long pI;
pid_t yP;
__asm__ volatile
(
"syscall\n\t"
:"=a"(pI)
:"a"(0x27)
: "rcx",
"r11",
"memory"
);
yP = (pid_t)pI;
printf("[+] Child PID : %d\n",
(int)yP);
long ret;
__asm__ volatile
(
"syscall\n\t"
:"=a"(ret)
: "a"(0x6E)
: "rcx",
"r11",
"memory"
);
printf("[+] Parent PID : %ld (dec : %d)\n",
ret, (int)ret);
avx();
}
else
{
printf("[+] Running PID : %d\n", getpid());
int sT = 0;
void* addr = NULL;
__asm__ volatile
(
"lea %[var], %%rax\n\t"
"mov %%rax, %[value]\n\t"
: [value] "=r" (addr)
: [var] "m" (sT)
: "rax"
);
printf("[+] Address Varaible Status : %p\n",(void *)addr);
long rV;
__asm__ volatile
(
"mov $0x3D, %%rax\n\t"
"mov %q[pidV], %%rdi\n\t"
"mov %q[sT], %%rsi\n\t"
"mov $0x0, %%rdx\n\t"
"xor %%r10, %%r10\n\t"
"syscall\n\t"
: "=a"(rV)
: [pidV] "r"(p),
[sT] "r"(&sT)
: "rcx",
"r11",
"memory"
);
p = (pid_t) rV;
printf("[+] Return Value (wait syscall) : %ld\n",(long)rV);
printf("[+] Status : %d\n", (int)sT);
if ((long)rV!= 0)
{
printf("[+] PID Finish Success.\n");
}
printf("[+] Parent process completed.\n");
}
}
int main()
{
printf(" \e[1;37m\t[ Byte Reaper ]\e[0m\n");
printf(" \e[1;37m[ AVX-Based Timing Side Channel ]\e[0m\n\n");
run();
__asm__ volatile
(
"xor %%rdi, %%rdi\n\t"
"mov $0xE7, %%rax\n\t"
"syscall\n\t"
:
:
: "rcx",
"r11",
"memory",
"rax",
"rdi"
);
}