x86_64执行Shellcode失败:

时间:2018-06-04 18:00:49

标签: python linux assembly x86-64 shellcode

我在64位Linux上使用Python 2.7。我有以下Python脚本,应该执行一个简单的Hello World shellcode。

import urllib2
import ctypes

shellcode = "\xb8\x01\x00\x00\x00\xbf\x01\x00\x00\x00\x48\xbe\xd8\x00\x60\x00\x00\x00\x00\xba\x0e\x00\x00\x00\x0f\x05\xb8\x3c\x00\x00\x00\xbf\x00\x00\x00\x00\x0f\x05"


#Create buffer in memory
shellcode_buffer = ctypes.create_string_buffer(shellcode, len(shellcode))

#Funktionszeiger
shellcode_func  = ctypes.cast(shellcode_buffer, ctypes.CFUNCTYPE(ctypes.c_void_p))

#Shellcode execute
shellcode_func()

如果我运行python Scriptname.py,我会收到内存访问错误。这里的任何人都知道为什么我的脚本不起作用?

编辑: 原始ASM代码:

section .data
    text db "Hello",10

section .text
    global _start

_start:
    ;syscall sys_write(1, text, 14)
    mov rax, 1
    mov rdi, 1
    mov rsi, text
    mov rdx, 14
    syscall

    ;syscall sys_exit(0)
    mov rax, 60
    mov rdi, 0
    syscall

1 个答案:

答案 0 :(得分:1)

您将需要python代码,使您的shellcode在具有读/写/执行权限的内存位置运行。因为它运行的shell代码所在的内存不在可执行内存中。您可以创建一个为您执行此操作的函数(testshellcode.py):

import ctypes, mmap, sys

# Convert string to bytes object. Differs between Python2 and Python3
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

# linux machine code
shellcode = "shell code string here"

# Create a pointer to our shell code and execute it with no parameters
create_shellcode_function(shellcode)()

代码应该与Python2.7 +和Python3一起使用

即使您将shell代码字符串插入上面测试程序中的字节对象,它也会失败。你的shell代码字符串似乎缺少字符串本身(hello);似乎没有正确编码,你依赖于text标签的静态内存位置。您将需要一个与位置无关的地址。

要修复代码以使其与位置无关,您可以使用RIP相对寻址。将字符串放在代码部分后面的.text内,完全忘记.data。此版本应该足够(shellcode.asm):

section .text
    global _start

_start:
    ;syscall sys_write(1, text, text_len)
    mov rax, 1
    mov rdi, 1
    lea rsi, [rel text]     ; RIP Relative addressing for Position independent code
    mov rdx, text_len       ; text length computed by assembler
    syscall

    ;syscall sys_exit(0)
    mov rax, 60
    mov rdi, 0
    syscall

    text db "Hello",10
text_len EQU $-text         ; Rather than hard coding length compute text length

使用OBJDUMP将shell代码程序转换为shell代码字符串可能会有问题。我写了一篇Stackoverflow Answer讨论了OBJDUMP方法的一些缺陷。如果要创建一个可执行文件来独立测试shell代码,那么最好将它组装并链接到可执行文件;使用OBJCOPY将可执行文件转换为二进制文件,然后使用某些东西(如HEXDUMP)将二进制文件转换为shell代码字符串。以下命令应该有效:

nasm -f elf64 shellcode.asm -o shellcode.o 
ld shellcode.o -o shellcode
objcopy -O binary shellcode shellcode.bin

如果您运行独立二进制文件shellcode,则应输出:

  

您好

然后,您可以使用以下内容将shellcode.bin转换为shell代码字符串

hexdump -v -e '"\\""x" 1/1 "%02x" ""' shellcode.bin

输出看起来像:

  

\ XB8 \ X01 \ X00 \ X00 \ X00 \ XBF \ X01 \ X00 \ X00 \ X00 \ X48 \ x8d \ X35 \ X13 \ X00 \ X00 \ X00 \ XBA \ X06 \ X00 \ X00 \ X00 \ X0F \ X05 \ XB8 \ X3C \ X00 \ X00 \ X00 \ XBF \ X00 \ X00 \ X00 \ X00 \ X0F \ X05 \ X48 \ X65 \ X6C \ X6C \ x6f \ X0A

然后,您可以在上面的python程序中插入此shell代码字符串(testshellcode.py),将 shell代码字符串替换为上面的字符串。您可以使用以下命令运行上面的脚本:

python testshellcode.py

输出应为:

  

您好

这是更高级的,并且有一些shell代码教程可以解释许多避免字符串中\x00个字节的技巧。

通常使用shell代码,您希望消除实际字符串漏洞的NUL(\x00)字节。执行此操作的shellcode.asm版本可能类似于:

section .text
    global _start

_start:
    jmp afterdata
    text db "Hello",10
text_len EQU $-text

afterdata:
    ;syscall sys_write(1, text, text_len)
    xor eax, eax
    inc eax
    mov edi, eax
    lea rsi, [rel text]
    xor edx, edx
    mov dl, text_len
    syscall

    ;syscall sys_exit(0)
    xor eax, eax
    mov al, 60
    xor edi, edi
    syscall

如果使用前面提到的命令创建shell代码字符串,HEXDUMP应该生成如下内容:

  

\ XEB \ X06 \ X48 \ X65 \ X6C \ X6C \ x6f \ X0A \ X31 \ XC0 \ XFF \ XC0 \ X89 \ xc7 \ X48 \ x8d \ X35 \固定的\ XFF \ XFF \ XFF \ X31 \ XD2 \ XB2 \ X06 \ X0F \ X05 \ X31 \ XC0 \ XB0 \ X3C \ X31 \ XFF \ X0F \ X05

此版本与您的代码完全相同,但请注意字符串中没有\x00个字节。运行时,它也应该打印:

  

您好