Вам понадобится код 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