Add execve arguments

Co-authored-by: Chris Gora <34940205+ChrisGora@users.noreply.github.com>
Co-authored-by: jack bond-preston <jackbondpreston@outlook.com>
This commit is contained in:
Liam Dalgarno
2020-11-28 17:42:09 +00:00
parent b38616fd71
commit f92b6e9ccd
5 changed files with 66 additions and 25 deletions

View File

@ -86,7 +86,7 @@ architectures supported:
parser.add_argument("--offset", type=str, metavar="<hexaddr>", help="Specify an offset for gadget addresses")
parser.add_argument("--paddingLen", type=int, metavar="<nbyte>", default=6, help="Specify the padding length for the ROP chain")
parser.add_argument("--ropFile", type=str, metavar="<string>", default="rop.txt", help="The file to write the generated ROP bytes to")
parser.add_argument("--execPath", type=str, metavar="<string>", default="/bin/sh", help="Path of the executable to make execve() run")
parser.add_argument("--execFile", type=str, metavar="<string>", default="/bin/sh", help="Path of the executable to make execve() run")
parser.add_argument("--ropchain", action="store_true", help="Enable the ROP chain generation")
parser.add_argument("--thumb" , action="store_true", help="Use the thumb mode for the search engine (ARM only)")
parser.add_argument("--console", action="store_true", help="Use an interactive console for search engine")

View File

@ -12,6 +12,7 @@ import re
import codecs
import ropgadget.rgutils as rgutils
import binascii
import json
from ropgadget.binary import Binary
from capstone import CS_MODE_32
@ -215,9 +216,12 @@ class Core(cmd.Cmd):
self.__getGadgets()
self.__lookingForGadgets()
if self.__options.ropchain:
with open(self.__options.execFile) as f:
exec_contents = json.load(f)
ROPMaker(
self.__binary, self.__gadgets, self.__options.paddingLen,
self.__options.ropFile, self.__options.execPath, self.__offset
self.__options.ropFile, exec_contents, self.__offset
)
return True

View File

@ -9,19 +9,18 @@
import re
from capstone import *
from textwrap import wrap
import sys
import math
from struct import pack
class ROPMakerX86(object):
def __init__(self, binary, gadgets, paddingLen, outFile, execPath, liboffset=0x0):
def __init__(self, binary, gadgets, paddingLen, outFile, exec, liboffset=0x0):
self.__binary = binary
self.__gadgets = gadgets
self.paddingLen = paddingLen
self.outFile = outFile
self.execPath = execPath
self.exec = exec
# If it's a library, we have the option to add an offset to the addresses
self.__liboffset = liboffset
@ -46,7 +45,7 @@ class ROPMakerX86(object):
if g != "ret":
if g.split()[0] == "ret" and g.split()[1] != "":
raise
print("# [+] Gadget found: 0x%x %s" %(gadget["vaddr"], gadget["gadget"]))
# print("# [+] Gadget found: 0x%x %s" %(gadget["vaddr"], gadget["gadget"]))
return [gadget, regex.group("dst"), regex.group("src")]
except:
continue
@ -64,7 +63,7 @@ class ROPMakerX86(object):
if g != "ret":
if g.split()[0] == "ret" and g.split()[1] != "":
raise
print("# [+] Gadget found: 0x%x %s" %(gadget["vaddr"], gadget["gadget"]))
# print("# [+] Gadget found: 0x%x %s" %(gadget["vaddr"], gadget["gadget"]))
return gadget
except:
continue
@ -121,24 +120,29 @@ class ROPMakerX86(object):
print("\n# [-] Error - Can't find a writable section")
return
print(f"dataAddr = 0x{dataAddr:08x}")
print(f"int 0x80 = 0x{syscall['vaddr']:08x}")
# prepend padding
p = bytes('A' * self.paddingLen, "ascii")
command = self.execPath
command = self.exec[0]
# split command into chunks of 4, prepend with /s as necessary
if len(command) % 4 > 0:
command = padding_len(len(command)) * "/" + command
command = padding_len(len(command)) * "/" + command
command_chunks = wrap(command, 4)
## EXEC (ARG0) \0 ARG1 \0 ARG2 \0 ... \0 PTR->EXEC PTR->ARG1 PTR->ARG2 ... \0 ##
args = ["test", "test1", "long string example"]
args = self.exec[1:]
chunked_args = []
for arg in args:
if len(arg) % 4 > 0:
arg = arg + padding_len(len(arg)) * "!"
chunked_args.append(wrap)
arg = arg + padding_len(len(arg)) * "!"
print(arg)
chunked_args.append(wrap(arg, 4))
print(chunked_args)
# & ( "cat" \0 )
exec_addr = dataAddr
@ -185,7 +189,24 @@ class ROPMakerX86(object):
# Write Argument Strings #
##########################
for i, arg in enumerate(chunked_args):
this_arg_addr = arg_addr[i]
for j, chunk in enumerate(arg):
address = this_arg_addr + (j * 4)
# write 4 char chunk of the command
p += self.__write4bytes(
address,
bytes(chunk, "ascii"),
dataAddr, popDst, popSrc, write4where
)
p += self.__write4nulls(
this_arg_addr + len(args[i]),
popDst, xorSrc, write4where
)
####################
# Write Argv Array #
@ -198,6 +219,13 @@ class ROPMakerX86(object):
dataAddr, popDst, popSrc, write4where
)
for i, address in enumerate(arg_addr):
p += self.__write4bytes(
argv_addr + ((i + 1) * 4),
pack('<I', address),
dataAddr, popDst, popSrc, write4where
)
# write null byte after argv array
p += self.__write4nulls(
argv_addr + (len(args) * 4) + 4,
@ -243,9 +271,9 @@ class ROPMakerX86(object):
# To find the smaller gadget
self.__gadgets.reverse()
print("\n# ROP chain generation\n# ===========================================================")
# print("\n# ROP chain generation\n# ===========================================================")
print("\n# - Step 1 -- Write-what-where gadgets\n")
# print("\n# - Step 1 -- Write-what-where gadgets\n")
gadgetsAlreadyTested = []
while True:
@ -274,7 +302,7 @@ class ROPMakerX86(object):
else:
break
print("\n# - Step 2 -- Init syscall number gadgets\n")
# print("\n# - Step 2 -- Init syscall number gadgets\n")
xorEax = self.__lookingForSomeThing("xor eax, eax")
if not xorEax:
@ -286,7 +314,7 @@ class ROPMakerX86(object):
print("# [-] Can't find the 'inc eax' instruction")
return
print("\n# - Step 3 -- Init syscall arguments gadgets\n")
# print("\n# - Step 3 -- Init syscall arguments gadgets\n")
popEbx = self.__lookingForSomeThing("pop ebx")
if not popEbx:
@ -303,14 +331,14 @@ class ROPMakerX86(object):
print("# [-] Can't find the 'pop edx' instruction")
return
print("\n# - Step 4 -- Syscall gadget\n")
# print("\n# - Step 4 -- Syscall gadget\n")
syscall = self.__lookingForSomeThing("int 0x80")
if not syscall:
print("# [-] Can't find the 'syscall' instruction")
return
print("\n# - Step 5 -- Build the ROP chain\n")
# print("\n# - Step 5 -- Build the ROP chain\n")
self.__buildRopChain(write4where[0], popDst, popSrc, xorSrc, xorEax, incEax, popEbx, popEcx, popEdx, syscall)
@ -319,3 +347,6 @@ class ROPMakerX86(object):
def padding_len(x):
return -(x % -4)
def wrap(str, n):
return [ str[i:i + n] for i in range(0, len(str), n) ]