Shellcode 适用于 Python 但不适用于 C

问题描述

实际上我正在尝试执行由 Asm x64 中的一个小程序创建的 shellcode,问题是它总是给我一个分段错误错误,即使我的 shellcode 是干净的并且我已经用正确的 C 编译了程序方式。

汇编代码:

global _start

section .text

_start:
    jmp code
    string: db "Hello world",0xa

code:
    add al,1
    xor rdi,rdi
    add rdi,1
    lea rsi,[rel string]
    xor rdx,rdx
    add rdx,12
    syscall

    xor rax,rax
    add rax,60
    xor rdi,rdi
    syscall

来自程序集的 Shellcode:

\xeb\x0c\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0a\x04\x01\x48\x31\xff\x48\x83\xc7\x01\x48\x8d\x35\xe4\xff\xff\xff\x48\x31\xd2\x48\x83\xc2\x0c\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05

C 代码:

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

unsigned char code[] = "\xeb\x0c\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0a\x04\x01\x48\x31\xff\x48\x83\xc7\x01\x48\x8d\x35\xe4\xff\xff\xff\x48\x31\xd2\x48\x83\xc2\x0c\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05";

int main() {
    printf("Shellcode Length:  %d\n",strlen(code));
    int (*ret)() = (int(*)())code;
    ret();
}

C 编译命令:

gcc -fno-stack-protector -z execstack execSC.c -o execSC

即使我尝试做一些像 "\x90" 这样简单的事情,我也有同样的问题

如果我尝试用 Python 运行相同的 shellcode,它可以工作并且不会给我分段错误错误

import ctypes,mmap,sys

# Check Python version
if sys.version_info >= (3,0):
    def b(string,charset='latin-1'):
        if isinstance(string,bytes) and not isinstance(string,str):
            return (string)
        else:
            return bytes(string,charset)
else:
    def b(string):
        return bytes(string)

def create_shellcode_function (shellcode_str):
    shellcode_bytes = b(shellcode_str)

# Allocate memory with a RWX private anonymous mmap
exec_mem = mmap.mmap(-1,len(shellcode_bytes),prot = mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC,flags = mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE)

# Copy shellcode from bytes object to executable memory
exec_mem.write(shellcode_bytes)

# Cast the memory to a C function object
ctypes_buffer = ctypes.c_int.from_buffer(exec_mem)
function = ctypes.CFUNCTYPE( ctypes.c_int64 )(ctypes.addressof(ctypes_buffer))
function._avoid_gc_for_mmap = exec_mem

# Return pointer to shell code function in executable memory
return function

shellcode = "shellcode"
create_shellcode_function(shellcode)()

解决方法

您的 Python 代码指定了 mmap.PROT_EXEC,这使得您编写 shell 代码区域的内存可执行。但是,unsigned char code[] = "..."; 直接写入可执行文件,稍后加载到不可执行内存中,这会阻止您执行 shell 代码。

现在,您指定了 -fno-stack-protector -z execstack,但 shell 代码不在堆栈中,因此这些选项并不重要。

如您所见 on Compiler Explorer,带有 shell 代码的字符串字面量位于 .data 部分,该部分标记为可执行。

C  : int (*ret)() = (int(*)())code;
ASM: mov    QWORD PTR [rbp-0x8],0x404060

所以我们知道 code 位于地址 0x404060,它属于 .data 部分。

来自 readelf -S 的输出:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [14] .text             PROGBITS         0000000000401050  00001050
       00000000000001a5  0000000000000000  AX       0     0     16
  [23] .got.plt          PROGBITS         0000000000404000  00003000
       0000000000000028  0000000000000008  WA       0     0     8
  [24] .data             PROGBITS         0000000000404040  00003040
       0000000000000054  0000000000000000  WA       0     0     32
  [25] .bss              NOBITS           0000000000404094  00003094
       0000000000000004  0000000000000000  WA       0     0     1
Key to Flags:
  W (write),A (alloc),X (execute),...

所以,存储可执行代码的.text的标志是AXSHF_ALLOC | SHF_EXECINSTR),所以允许执行,但是{{1}的标志},您的 shell 代码的存储位置是 .data,没有 WA - 所以不允许执行。


但是,如果您将 X 放在 unsigned char code[] = "..."; 函数中,everything will run fine 因为现在 shell 代码将在堆栈中:

main

但是,使用 ASM generation compiler returned: 0 Execution build compiler returned: 0 Program returned: 0 Hello world 编译时仍然会崩溃,这可以通过将 -O3 声明为 code (https://godbolt.org/z/TG8aGe6c4) 来修复。

现在这个代码:

volatile

编译为:

int (*ret)() = (int(*)())code;
ret();

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...