x86_64 Executing Shellcode fails:

风格不统一 提交于 2019-12-02 09:06:38

You are going to need python code that makes your shellcode run in a memory location that has Read/Write/Execute privileges. As it is the memory your shell code is running from is not in executable memory. You can create a function that does this for you (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)()

The code should work with Python2.7+ and Python3


Even if you insert your shell code string into the byte object in the test program above it will fail. Your shell code strings seem to be lacking the string itself (hello); doesn't seem to be encoded properly and you rely on a static memory location for the textlabel. You will need an address that is position independent.

To fix the code so it is position independent you can use RIP relative addressing. Place the string inside the .text after the code section and forget about .data altogether. This version should suffice (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

Using OBJDUMP to convert a shell code program to a shell code string can be problematic. I wrote a Stackoverflow Answer discussing some of the pitfalls of the OBJDUMP method. If you are creating an executable to test your shell code standalone then it is preferable to assemble and link it to an executable; use OBJCOPY to convert the executable to binary and then use something (like HEXDUMP) to convert the binary to a shell code string. The following commands should work:

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

If you run the standalone binary shellcode it should output:

Hello

You can then convert shellcode.bin to a shell code string with:

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

The output would look something like:

\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

You can then insert this shell code string in the python program above (testshellcode.py) replacing shell code string here with the string above. You can run the script above with:

python testshellcode.py

The output should be:

Hello


This is more advanced, and there are shell code tutorials that explain many of the tricks to avoid \x00 bytes in a string.

Usually with shell code you want to eliminate NUL (\x00) bytes for real string exploits. A version of shellcode.asm that does this could look something like:

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

If you create shell code string with the commands mentioned previously, HEXDUMP should produce something like:

\xeb\x06\x48\x65\x6c\x6c\x6f\x0a\x31\xc0\xff\xc0\x89\xc7\x48\x8d\x35\xed\xff\xff\xff\x31\xd2\xb2\x06\x0f\x05\x31\xc0\xb0\x3c\x31\xff\x0f\x05

This version does the same thing as your code but notice there are no \x00 bytes in the string. When run, it too should print:

Hello

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!