x86_64 Не удается выполнить Shellcode: - PullRequest
0 голосов
/ 04 июня 2018

Я использую Python 2.7 на 64-битном Linux.У меня есть следующий скрипт Python, который должен выполнить простой шелл-код Hello World.

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 голосов
/ 05 июня 2018

Вам понадобится код Python, который заставляет ваш шелл-код работать в ячейке памяти с правами чтения / записи / выполнения.Так как это память, из которой выполняется ваш шелл-код, нет в исполняемой памяти.Вы можете создать функцию, которая сделает это за вас (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


, даже если вы вставите свойстрока кода оболочки в объекте байта в тестовой программе выше, это потерпит неудачу.Кажется, что в ваших строках шелл-кода отсутствует сама строка (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 для преобразования программы с кодом оболочки в строку кода оболочки может быть проблематичным.Я написал Stackoverflow Answer , в котором обсуждаются некоторые подводные камни метода OBJDUMP.Если вы создаете исполняемый файл для тестирования автономного шелл-кода, то предпочтительно собрать его и связать с исполняемым файлом;используйте OBJCOPY для преобразования исполняемого файла в двоичный, а затем используйте что-то (например, HEXDUMP) для преобразования двоичного файла в строку кода оболочки.Должны работать следующие команды:

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

Если вы запустите автономный двоичный файл shellcode, он должен вывести:

Hello

Затем вы можетепреобразовать shellcode.bin в строку кода оболочки с помощью:

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 (testshellcode.py), заменив строка кода оболочки здесь со строкой выше.Вы можете запустить приведенный выше скрипт с помощью:

python testshellcode.py

Вывод должен быть:

Hello


Это более продвинутый, иСуществуют учебники по шелл-коду, которые объясняют многие приемы, позволяющие избежать \x00 байтов в строке.

Обычно с помощью шелл-кода вы хотите исключить 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

Если вы создаете строку кода оболочки с помощью команд, упомянутых ранее, 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 байтов,При запуске он также должен вывести:

Hello

...